1. 程式人生 > >常用會話管理方式

常用會話管理方式

功能 pos 傳遞 集群部署 時間 mar 返回 其它 ora

會話管理方式

http是無狀態的,這就意味著客戶端即使第一次請求已經驗證了身份,但是第二次請求的時候服務器僅通過http連接並不能知道是那個用戶。但是我們是需要狀態管理的,比如用戶登錄了才能做一些其它操作,這就需要我們進行會話管理。

這裏主要講兩種管理方式

  • 基於session的管理方式
  • 基於ticket管理方式

1. 基於session的方法

  1. 客戶端送第一次請求後,服務端在服務器創建session信息,並將sessionid傳送給瀏覽器

第一次請求

技術分享圖片

第一請求並沒有帶cookie信息,服務器返回set-cookie字段,並帶有sessionid(laralve_session)

  1. 客戶端再次請求會通過cookie帶著這個sessionid
    再次請求

技術分享圖片

因為上次的響應有set-cookie字段,將sessionid儲存到cookie中,現在請求已經帶著cookie字段,裏面包含sessionid

3.這樣我們就可以通過這個sessionid進行用戶狀態管理。

實際上上面的session並不具備會話管理功能,但是我們可以將我們的用戶狀態放到session對象裏面,並存儲在服務端。用戶登錄成功後,我們將登錄憑證存儲在session對象中,這樣服務端在收到sessionid的時候就可以判斷對應的session對象是否含有登錄憑證,如果有則證明登錄成功。

問題:

  1. session信息需要存儲在服務端,信息過多會占用較多內存
  2. 服務器集群部署,多臺服務器之間session信息不共享
  3. cookie要存儲在域名下,如果同屬於一級域名下比較好解決,但是如果不同域就有些麻煩,不能跨域,這就需要針對性解決

在實際部署中我們可能會使用redis存儲,這樣可以減輕服務器壓力,也能解決服務器session共享問題

2. 基於ticket的方式

用戶登錄信息合法,服務端產生ticket信息,響應中將ticket信息傳遞給客戶端,客戶端並將ticket信息存儲在客戶端,以後每次請求的時候帶著ticket信息,服務端收到每次請求後都驗證ticket是否存在並且合法有效,來確認用戶是否登錄

  1. 用戶使用用戶名密碼登錄,服務端驗證服務名密碼是否正確,如果正確則創建登錄憑證,這個登錄憑證可能包含著用戶id,過期時間等。
  2. 將登錄憑證+簽名+其它加密處理,然後將加密處理的字符串存儲到客戶端。
  3. 客戶端發送請求後,服務端每次檢測是否有此ticket信息,如果有則解密處理,查看簽名是否正確,是否過期等等,如果都合法則說明用戶登錄有效。

問題:

  1. 儲存的用戶信息過多,導致ticket過大,如果使用cookie存儲的話,cookie大小有限制,加密字符串過長的話會引發其他問題
  2. 每次請求都要帶著ticket信息,ticket信息又比較大,降低訪問性能
  3. 過期自動刷新問題

實際上在客戶端ticket字符串不一定非要存儲在cookie中,我們還可以存儲在localstorage,sessionstroage等的地方。只要我們每次請求的時候取得這個ticket信息並且讓服務端知道就可以表明身份。

關於這種方式,可以符合現成的標準JWT,這樣就比較規範了,有興趣的可以了解。

3. 總結

  1. 比較下上面兩種方式,基於session的方式將用戶憑證保存在服務端,基於ticket的方式保存在客戶端。
  2. 只要不泄露以上的兩種會話機制還是比較安全的,各有各的應用場景,根據自身情況來處理
  3. 以上都沒有避免sessionid,ticket(加密字符串)的泄露問題,一旦泄露別人就可以冒充我們,做一些不可告人的事情。關於傳輸過程中的竊取可以使用https來避免,在客戶端的憑證竊取需要我們自己註意了,比如laravel就使用csrf_token來避免CSRF攻擊。

參考資料

http://www.cnblogs.com/lyzg/p/6067766.html

常用會話管理方式