[Rails]Session、Cookie和Flash

in #ruby6 years ago (edited)

在Rails中Cookies、Sessions還有Flashes是三種特殊的object,他們使用起來就像是hash一樣。

以下會介紹他們三個在Rails中的使用情境。

Session

在網頁中,由於HTTP是stateless的特性(也就是說server無法在不同的request/response cycle中記住資訊),所以每次request對server來說都是全新的request一樣,server無法得知上個request的狀態。

在實作上,我們會透過在每次client和server間的request加入一個特別的token(也就是session id),讓server知道這些request是來自於哪個使用者、又該紀錄怎樣的狀態。

所以實際上HTTP依舊是statelessness,但是我們透過傳遞session id,讓每次的請求都保持著連線。

舉例來說,當你登入FB後開始瀏覽動態,如果你想針對某個好友的動態點讚,如果沒有任何的東西幫你記憶你目前的狀態,Server會不知道這個request是哪個使用者送出(事實上是你)

在實務上session id常會被存在cookie當中,在每次的request/response中傳遞。

一般來說,每個送到server的request都會經歷以下的過程

  • Server檢查request中是否含有session id
  • 如果有session id,確認此session id是否有效
  • server叫出相對應的資料,並回傳給client端

在Rails中有四種機制來儲存session

  1. ActionDispatch::Session::CookieStore - Stores everything on the client.
  2. ActionDispatch::Session::CacheStore - Stores the data in the Rails cache.
  3. ActionDispatch::Session::ActiveRecordStore - Stores the data in a database using Active Record. (require activerecord-session_store gem).
  4. ActionDispatch::Session::MemCacheStore - Stores the data in a memcached cluster (this is a legacy implementation; consider using CacheStore instead).

Session除了幫助server記錄狀態外,也可以儲存少量的data。

在Rails中預設使用CookieStore這個選項來儲存session。這個選項最大的不同在於會將所有的session資訊存在cookie當中(經過加密),而不是單純透過存取session id,然後向server取得資料。Server可以直接透過cookie得到session德資料。

以下是在Rails常見的session用法

# Set a session value
session[:current_user_id] = user.id

# Access a session value
some_other_variable_value = session[:other_variable_key]

# Reset a session key
session[:key_to_be_reset] = nil

# Reset the entire session
reset_session

Cookie

我們可以把cookie想像成一個被存在client中的小資料庫,當client端送出請求到server時,會連帶的將這些資料一併傳到server端。而讓server跟client端保持連線的session id,也是被存在cookie中傳送到server端(與將資料存在client端的cookie相對應的,就是將資料存在server端的session)。

像是我們去購物網站購物時,即使我們沒有登入或著註冊該公司的會員身份,仍能夠將商品加入購物車當中。就是因為應用了cookie將資料儲存在瀏覽器上,所以在使用購物網站時,商品才能夠持續顯示在購物車中。

在上面的內容中我們有提到,Rails中是將session hash存在cookie裡。而由於session中常會有很多機密的資訊,所以Rails的使用了ActionDispatch::Cookies::ChainedCookieJars的module,讓cookie可以被加密,只有server才知道如何解開,避免在clinet端被讀取跟更改。

一般來說我們不會在cookie裡放入太多資料,因為cookie的儲存上限大約4kb。

以下是在Rails常見的cookie用法

# set a cookie value
cookies[:commenter_name] = @comment.author

# Delete cookie for the commenter's name cookie
cookies.delete(:commenter_name)

# Set cookie value with expiration dates
cookies[:name] = { value: "cookies YUM", expires: Time.now + 3600}.

Flash

Flash是session的一部分,而會在下次的request中出現並且被清掉,所以很適合用來顯示提示訊息。

如果你想要讓flash在當前的request就出現,你可以用 flash.now來達成這個目的。

def create
  @user = User.new
  if @user.save
    flash[:success] = "User was created"
    redirect_to user_path(@user)
  else
    flash.now[:error] = "Could not save user"
    render action: "new"
  end
end

參考資料:
Action Controller Overview
SESSIONS, COOKIES, AND AUTHENTICATION
Class ActionDispatch::Cookies < Object
Module ActionDispatch::Cookies::ChainedCookieJars
Web 技術中的 Session 是什麼?