session,cookie和token
session,cookie和token究竟是什麼
簡述
cookie,session,token作為面試必問題,很多同學能答個大概,但是又迷糊不清,希望本篇文章對大家有所幫助
http是一個無狀態協議
什麼是無狀態呢?就是說這一次請求和上一次請求是沒有任何關係的,互不認識的,沒有關聯的。這種無狀態的的好處是快速。
cookie和session
由於http的無狀態性,為了使某個域名下的所有網頁能夠共享某些資料,session和cookie出現了。客戶端訪問伺服器的流程如下
- 首先,客戶端會發送一個http請求到伺服器端。
- 伺服器端接受客戶端請求後,建立一個session,併發送一個http響應到客戶端,這個響應頭,其中就包含Set-Cookie頭部。該頭部包含了sessionId。Set-Cookie格式如下,具體請看Cookie詳解
Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]
- 在客戶端發起的第二次請求,假如伺服器給了set-Cookie,瀏覽器會自動在請求頭中新增cookie
- 伺服器接收請求,分解cookie,驗證資訊,核對成功後返回response給客戶端
注意
- cookie只是實現session的其中一種方案。雖然是最常用的,但並不是唯一的方法。禁用cookie後還有其他方法儲存,比如放在url中
- 現在大多都是Session + Cookie,但是隻用session不用cookie,或是隻用cookie,不用session在理論上都可以保持會話狀態。可是實際中因為多種原因,一般不會單獨使用
- 用session只需要在客戶端儲存一個id,實際上大量資料都是儲存在服務端。如果全部用cookie,資料量大的時候客戶端是沒有那麼多空間的。
- 如果只用cookie不用session,那麼賬戶資訊全部儲存在客戶端,一旦被劫持,全部資訊都會洩露。並且客戶端資料量變大,網路傳輸的資料量也會變大
cookie和session通俗小結
簡而言之, session 有如使用者資訊檔案表, 裡面包含了使用者的認證資訊和登入狀態等資訊. 而 cookie 就是使用者通行證
token定義
token 也稱作令牌,由uid+time+sign[+固定引數] token 的認證方式類似於臨時的證書籤名, 並且是一種服務端無狀態的認證方式, 非常適合於 REST API 的場景. 所謂無狀態就是服務端並不會儲存身份認證相關的資料。
token組成
- uid: 使用者唯一身份標識
- time: 當前時間的時間戳
- sign: 簽名, 使用 hash/encrypt 壓縮成定長的十六進位制字串,以防止第三方惡意拼接
- 固定引數(可選): 將一些常用的固定引數加入到 token 中是為了避免重複查庫
存放
token在客戶端一般存放於localStorage,cookie,或sessionStorage中。在伺服器一般存於資料庫中
token認證流程
token 的認證流程與cookie很相似
- 使用者登入,成功後伺服器返回Token給客戶端。
- 客戶端收到資料後儲存在客戶端
- 客戶端再次訪問伺服器,將token放入headers中
- 伺服器端採用filter過濾器校驗。校驗成功則返回請求資料,校驗失敗則返回錯誤碼
token可以抵抗csrf,cookie+session不行
因為form 發起的 POST 請求並不受到瀏覽器同源策略的限制,因此可以任意地使用其他域的 Cookie 向其他域傳送 POST 請求,形成 CSRF 攻擊。在post請求的瞬間,cookie會被瀏覽器自動新增到請求頭中。但token不同,token是開發者為了防範csrf而特別設計的令牌,瀏覽器不會自動新增到headers裡,攻擊者也無法訪問使用者的token,所以提交的表單無法通過伺服器過濾,也就無法形成攻擊。
分散式情況下的session和token
我們已經知道session時有狀態的,一般存於伺服器記憶體或硬碟中,當伺服器採用分散式或叢集時,session就會面對負載均衡問題。
- 負載均衡多伺服器的情況,不好確認當前使用者是否登入,因為多伺服器不共享session。這個問題也可以將session存在一個伺服器中來解決,但是就不能完全達到負載均衡的效果。當今的幾種解決session負載均衡的方法。
而token是無狀態的,token字串裡就儲存了所有的使用者資訊
- 客戶端登陸傳遞資訊給服務端,服務端收到後把使用者資訊加密(token)傳給客戶端,客戶端將token存放於localStroage等容器中。客戶端每次訪問都傳遞token,服務端解密token,就知道這個使用者是誰了。通過cpu加解密,服務端就不需要儲存session佔用儲存空間,就很好的解決負載均衡多伺服器的問題了。這個方法叫做JWT(Json Web Token)
總結
- session儲存於伺服器,可以理解為一個狀態列表,擁有一個唯一識別符號sessionId,通常存放於cookie中。伺服器收到cookie後解析出sessionId,再去session列表中查詢,才能找到相應session。依賴cookie
- cookie類似一個令牌,裝有sessionId,儲存在客戶端,瀏覽器通常會自動新增。
- token也類似一個令牌,無狀態,使用者資訊都被加密到token中,伺服器收到token後解密就可知道是哪個使用者。需要開發者手動新增。
- jwt只是一個跨域認證的方案
補充:JWT
JWT就是token的一種實現方式,並且基本是java web領域的事實標準。
JWT全稱是JSON Web Token。基本可以看出是使用JSON格式傳輸token
JWT 由 3 部分構成:
Header :描述 JWT 的元資料。定義了生成簽名的演算法以及 Token 的型別。Payload(負載):用來存放實際需要傳遞的資料Signature(簽名):伺服器通過Payload、Header和一個金鑰(secret)使用 Header 裡面指定的簽名演算法(預設是 HMAC SHA256)生成。流程:
在基於 Token 進行身份驗證的的應用程式中,使用者登入時,伺服器通過Payload、Header和一個金鑰(secret)建立令牌(Token)並將 Token 傳送給客戶端,
然後客戶端將 Token 儲存在 Cookie 或者 localStorage 裡面,以後客戶端發出的所有請求都會攜帶這個令牌。你可以把它放在 Cookie 裡面自動傳送,但是這樣不能跨域,所以更好的做法是放在 HTTP Header 的 Authorization欄位中:Authorization: 你的Token。