Cookie vs. Session

1 minute read

Cookie 跟 Session 的相異與相同之處、原理介紹,還有什麼時候該用哪個?

Cookie 是一堆 key1=value1, key2=value2….的資料,它存在你的http header 裡,例如底下的輸出,你可以看到 cookie 裡有很多 (key, value)的pair。

Host:"www.facebook.com"
User-Agent:"Mozilla/5.0 (X11; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0"
Accept:"*/*"
Accept-Language:"en-US,en;q=0.5"
Accept-Encoding:"gzip, deflate, br"
DNT:"1"
Referer:"https://www.facebook.com/"
Cookie:"datr=j1g500FtNKx; lu=gQYwJLi7pI_Y9w; csm=2; p=-2; ......."
Connection:"keep-alive"

因為 http 是 stateless 的協定,它會忘記你上一次做了什麼,沒有記憶的機制,因此就用 cookie 來存上一次請求的部份結果,例如底下是許多網站常有的 「自動登入」機制,讓你不用每次都要重新登入,便是這個原理。

要注意的是他有大小限制,一般瀏覽器實做 cookie 上限是 4K,此外,它既然包含在 http header 中,代表著每一次向 server 的請求,都需要夾帶這個 cookie,如果你在裡面存放了大量的資料,那資料傳輸的速度就可想而知了。

另外,因為它會在傳輸過程中用明碼儲存,這意味著 cookie 不適合夾帶敏感資料,可能會被人竊聽,偷走你的 cookie 。如果正好網站又是單純依靠 cookie 判斷使用者身份,那麼它就能利用你的身份登入。

Session

Cookie 有 4K 大小的限制 (事實上 RFC 規定並非如此),所以解決之道就是讓 client 只存 session id ,詳細的 key=value 的配對存在 server 端。 這樣一來可以避免 http header 中每次都要加上巨大 cookie 傳來傳去的問題,也可將一些敏感的資料,如密碼等等存在 server 端,也可以防止 client 端亂改資料,因為 session 存在於 server 上。

server 端靠著 cookie 裡獨一無二的 id 判斷使用者身份,讓它存取裡面的key/value 。這樣一來,也會有安全性問題,如果別人偷走了你的 cookie,且網站沒有詳細檢查你的身份,就能用你的帳號 (session id) 登入。

例如下面這個 curl -v 的輸出,便是依靠 cookie 裡的 phpsessid,到 server 端在判斷使用者是誰。

 HTTP/1.1 200 OK
< Date: Sun, 24 Jul 2016 08:21:08 GMT
< Server: Apache/2.4.7 (Ubuntu)
< X-Powered-By: PHP/5.5.9-1ubuntu4.17
< Set-Cookie: PHPSESSID=34372d61646d696e; path=/; HttpOnly
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< Pragma: no-cache
< Vary: Accept-Encoding
< Content-Length: 1080
< Content-Type: text/html
< Connection: keep-alive

這些防護措施在 Allen Own/DEVCORE 戴夫寇爾 blog 有提到解法,詳情可以參考他的文章。

參考資料