iT邦幫忙

2024 iThome 鐵人賽

DAY 25
1
Software Development

從零開始的後端學習之旅系列 第 25

DAY25 Session vs. Cookie:如何讓你的網站記住使用者?

  • 分享至 

  • xImage
  •  

前言

昨天提到了幾種驗證(Authentication)的方式,其中有一個是 session-based 的驗證方式,那什麼是session,而session 跟 cookie 又很常會被一起討論,那他們又是什麼?區別是什麼?

為什麼需要 Session?

先來看一下RFC 2109的敘述吧:

This document describes a way to create stateful sessions with HTTP
requests and responses. Currently, HTTP servers respond to each
client request without relating that request to previous or
subsequent requests; the technique allows clients and servers that
wish to exchange state information to place HTTP requests and
responses within a larger context, which we term a "session".

HTTP 協定是無狀態(stateless)的,每個瀏覽器所發送的請求都是互相沒有關連的,是獨立的請求,可以想像以下場景:

小明每天都會去他家附近的六十嵐買飲料,他都固定喝四季春無糖微冰。過了半個月後,小明想說:『我每天都喝一樣的飲料,店員應該看到我就知道我要喝什麼了吧!』於是,他就充滿自信地走到店員的前面,殊不知,因為店員根本就沒有在記客人的長相以及喜好,還是對小明說:『請問要點什麼呢?』

HTTP 就像是上面那個什麼都沒有記住的店員,所以瀏覽器每次都要重新發出一次完整的請求,HTTP 才有辦法進行處理。雖然這種模式對於伺服器的橫向擴展是很方便的,因為不需要在每個伺服器中同步使用者的狀態,不過在有些情況下會帶給使用者不好的體驗。
想像一下,今天在購物網站時,你好不容易找到了CP值高的商品,加進購物車後,電腦卻突然當機了,結果重新開機進入網站後,發現購物車是空的,因為狀態並沒有被記住,所以你又要花很多時間去重新找那樣商品,這樣不是很麻煩嗎?
而透過 Session 機制,可以保持用戶的狀態並記錄在一段時間內的請求,這使得伺服器能夠根據這些請求的歷史記錄做出相應的回應。這樣,使用者在互動過程中不必每次都重新提供資訊,進而提升了整體的使用體驗。

Cookie 又是什麼?

先來看一下RFC 2109的敘述吧:

This document specifies a way to create a stateful session with HTTP
requests and responses. It describes two new headers, Cookie and
Set-Cookie, which carry state information between participating
origin servers and user agents.

透過 Cookie 這個 header 可以在伺服器以及使用者端加入狀態訊息,讓 HTTP 的請求以及回應具有狀態,也就是說,Cookie 可以看作是 Session 的載體。

因為上述的店員都沒有在記住熟客的長相以及喜好,讓熟客都覺得他很不好相處、沒有親切感,客人感受不到賓至如歸的感覺,於是都會跟店長投訴他。店長因為常常接受到投訴,也覺得很煩,就決定要求店員限期改善,否則就要開除他。這時候店員想到了一個辦法,他發給每個客人一張會員卡,上面記錄了這個客人常常點的飲料是什麼,於是只要每個客人來買飲料,店員只要看到會員卡的內容,就知道客人的需求啦~

於是在使用者在網路上操作購物時,瀏覽器與伺服器間的請求會如下流程:

  1. 瀏覽器向伺服器發出登入的請求
    POST /acme/login HTTP/1.1
    [form data]
    
  2. 伺服器向瀏覽器發出 Set-Cookie 的 header,紀錄了使用者的登入資訊
    HTTP/1.1 200 OK
    Set-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"
    
  3. 使用者將商品加入購物車,瀏覽器向伺服器發出請求
    POST /acme/pickitem HTTP/1.1
    Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"
    [form data]
    
  4. 伺服器向瀏覽器發出 Set-Cookie 的 header,紀錄了使用者放入購物車的商品
    HTTP/1.1 200 OK
    Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";
    Path="/acme"
    
  5. 使用者選擇運送方式,例如宅配或便利商店取貨,瀏覽器向伺服器發出請求
    POST /acme/shipping HTTP/1.1
    Cookie: $Version="1";
    Customer="WILE_E_COYOTE"; $Path="/acme";
    Part_Number="Rocket_Launcher_0001"; $Path="/acme"
    [form data]
    
  6. 伺服器向瀏覽器發出 Set-Cookie 的 header,紀錄了使用者選擇的送貨方式
    HTTP/1.1 200 OK
    Set-Cookie: Shipping="FedEx"; Version="1"; Path="/acme"
    
  7. 使用者進行結帳,處理訂單
    POST /acme/process HTTP/1.1
    Cookie: $Version="1";
    Customer="WILE_E_COYOTE"; $Path="/acme";
    Part_Number="Rocket_Launcher_0001"; $Path="/acme";
    Shipping="FedEx"; $Path="/acme"
    [form data]
    
  8. 伺服器回傳交易完成
    HTTP/1.1 200 OK
    

Session 如何實作?

知道了 Session 以及 Cookie 是什麼,那 Session 有哪些方式進行實作呢?

  1. URL-based Session:將 Session 紀錄在網址列中,所以如果像是上面的例子,使用者要進行結帳,處理訂單的時候,網址列會長成以下的樣子:

    GET /acme/process?Customer=WILE_E_COYOTE&Part_Number=Rocket_Launcher_0001&Shipping=FedEx HTTP/1.1
    

    不過如果將訂單資訊,甚至是 Session ID 透過網址列進行傳送的話,安全性容易出現很大的漏洞,因此現在通常都會使用以下兩種方式實作 Session。

  2. Cookie-based Session:將所有 Session 的資訊都放在 Cookie 中,由瀏覽器進行明文或是編碼保存,在後續的請求中就會送出帶有所有 Session 資訊的 Cookie,而因為只會通過明文或編碼保存,Cookie 中不應該存放機密資料,且需要通過安全的方式傳送,如HTTPS。

  3. SessionID:就如以下RFC 6265所述

    Using the Set-Cookie header, a server can send the user agent a short
    string in an HTTP response that the user agent will return in future
    HTTP requests that are within the scope of the cookie. For example,
    the server can send the user agent a "session identifier" named SID
    with the value 31d4d96e407aad42. The user agent then returns the
    session identifier in subsequent requests.

    將 Session 的資訊都存在 server 中,只有將 Session 的 ID 放入 Cookie 並傳送給瀏覽器進行保存,在後續的請求中只會帶有 Session ID,伺服器透過 Session ID 去資料庫尋找匹配資訊以回復 Session 狀態。

小結

今天介紹了關於 Session 以及 Cookie 的概念,以及 Session 實作的一些方式,希望能夠幫助大家對於這兩者有更多的認識~
/images/emoticon/emoticon29.gif

參考資料

白話 Session 與 Cookie:從經營雜貨店開始
淺談 Session 與 Cookie:一起來讀 RFC
RFC 2109
RFC 6265


上一篇
DAY24 探索身份驗證的世界:三種方法的解析
下一篇
DAY26 OAuth 1.0:你所不知道的安全授權背後的故事
系列文
從零開始的後端學習之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言