Skip to main content

[探索 3 分鐘] session 與 cookies


Web 開發者除了必須了解 HTTP 協定, session 與 cookies 大概也是數一數二重要的概念了。最近不小心爬文爬到 2005 年 Cookieless ASP.NET 這篇文章, 覺得挺有趣, 這邊筆記一下重點。

概念

wiki 關於 HTTP session state 的解釋
HTTP is a stateless protocol. A stateless protocol does not require the HTTP server to retain information or status about each user for the duration of multiple requests. However, some web applications implement states or server side sessions using for instance HTTP cookies or hidden variables within web forms.
HTTP 本身是一種無狀態的協定, 這是天生的。所以 session state 其實是一個人工的產物, 微軟在 1997 年推出 ASP 技術時提到這個概念。session state 可以讓應用程序保存 user 的部分資訊做為持續互動用途。每個 session 會有一個唯一的 ID (字符串), 瀏覽器若啟用 cookies 機制則 session ID 會存入 cookies 中 (或其他 hidden 欄位中), 客戶端每次發出 request 的封包內就會夾帶這個 session ID 供伺服器驗證並取回先前資料用。

Cookies 是有問題的東西 ?

cookies 好像是個麻煩精 ? 他其實只是一堆文字形式的 key value 組合, 儲存於客戶端, 依據建立連線的 domain 為名的資料夾中, 本身並不是一隻程式, 所以不會有攻擊行為。但就是因為是一個單純的檔案以及文字, 任何安裝於客戶機器上的電腦, 都有機會取得內容, 有些敏感信息可能因此曝光, 更惡意的還可能竄改資料。

使用 Cookieless Sessions

如果因為瀏覽器被取消 cookie 功能或是要支持 Mobile 應用, 不使用 Cookies 是很有可能的場景。如 cookieless 的表單驗證, cookieless session, 在 ASP, ASP.NET, ASP.NET MVC 都可以使用, 但未來微軟傾向不支持 (請參考 What not to do in ASP.NET, and what to do instead), 這裡僅是探討怎麼實做。
<sessionState cookieless="true" />
<sessionState cookieless="true" timeout="20" />
web.config > sessionState 給予 cookieless = "true" 的額外屬性, 就可以啟用 cookieless。然後系統就變身了, 看一下這個烘培機 (home page), 有沒有哪裡怪怪的 ?
原來 session ID 內嵌在 url 中間了, 那的確就不需要 cookies
http://host/application/(session ID here)/index
http://host/application/(A(XXXX)S(XXXX)F(XXXX))/index
但因為我們只能依賴網址告訴 Application 我是誰, 副效應就是會有同一個 user session 覆蓋的問題 (比如開 2 個分頁登入 2 次, 前一次的 session 其實就失效了, 但你不會知道直到送出了表單...), 或是複製網址給自己同事時, 會很像亂碼。就開發而言, 程式碼看到的網址, 不是 runtime 呈現的網址, 或是 session ID 過長造成網址被截斷。

開發建議

純個人經驗分享, 要控制 session, 越往大型系統架構規劃時, 建議儘量朝以下方向設計:
  • 預設使用 Cookies, 但不儲存用戶資訊 (包括 name, email), 僅存驗證用的 ID (但也不是 account ID)
  • 使用雜湊函數, 或 Guid 生成 session ID 時, 採用較安全的演算法 (如 SHA 256), 儲存長度 64 以上。不要再使用 MD5 了, 會被破解
  • session ID 生成時, 隱含以下信息: useragent, ip, account ID, mac, created time, expired time (把 schema 訂好後, 可以用 JSON 物件序列化為字串), 一旦比對前後 request 的內容被變更了, 系統要有對應動作
  • 無狀態伺服器。伺服器是可能重啟的, 系統也可能是分散式的。把用戶的 session 儲存在單一主機, 將面臨維護以及水平擴充困難
  • 用 HTTP 標頭的方式儲存登入後的驗證 ID, 或有人稱為 token, session, appToken。OAuth 驗證也是儲存於Authorization Header

參考資料

  • https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP_session
  • https://msdn.microsoft.com/en-us/library/aa479314.aspx#cookieless_topic1
  • https://msdn.microsoft.com/en-us/library/aa479315.aspx
  • https://docs.microsoft.com/en-us/aspnet/aspnet/overview/web-development-best-practices/what-not-to-do-in-aspnet-and-what-to-do-instead#cookieless
  • https://technet.microsoft.com/en-us/library/84338f84-9a77-48c7-aeba-75cfa740859f
  • https://github.com/aspnet/Session
  • https://zh.wikipedia.org/wiki/SHA%E5%AE%B6%E6%97%8F
  • https://stackoverflow.com/questions/623815/what-is-the-difference-between-a-session-and-a-cookie

Comments