前言
之前看了不少同型別的文章,對于Cookie和Session真是眾說紛紜,有的人說先有Cookie才有Session,也有的人說現有Session再有Cookie,我也說說我的理解,希望對大家有所幫助,
注:需要讀者對于Cookie/Session/Token有基本的了解,

Cookie和Session
說這倆之前,先說http,它是一個無狀態協議,
怎么理解呢?就是說連續的兩次請求之間是沒有任何關聯的,這樣的好處是快速,壞處是想要把同個域名下的兩個頁面關聯起來,必須使用某些手段和工具,
這就引出了我們要說的Cookie和Session,
讓我們用文字+圖片了解一下客戶端訪問服務器的流程:
? 首先,客戶端會發送一個http請求到服務器端;
? 服務器端接受客戶端請求后,建立一個Session,并發送一個http回應到客戶端,這個回應頭,其中就包含Set-Cookie頭部,該頭部包含了SessionId;
? 在客戶端發起的第二次請求,假如服務器給了Set-Cookie,瀏覽器會自動在請求頭中添加Cookie;
? 服務器接收請求,分解Cookie,驗證資訊,核對成功后回傳response給客戶端,

這里有幾點要注意的:
? Cookie只是實作Session的其中一種方案,雖然是最常用的,但并不是唯一的方法,禁用Cookie后還有其他方法存盤,比如放在url中;
? 單一使用Session不用Cookie,或者反過來只用Cookie不用Session,在理論上都可以保持會話狀態,只是實際操作中因為多種原因,大多都是Session + Cookie;
? 用Session只需要在客戶端保存一個id,實際上大量資料都是保存在服務器端,如果全部用Cookie,資料量大的時候客戶端是沒有那么多空間的;
? 如果只用Cookie不用Session,那么賬戶資訊全部保存在客戶端,一旦被劫持,全部資訊都會泄露,并且客戶端資料量變大,網路傳輸的資料量也會變大,
簡單總結,就是Session 有點像用戶資訊檔案表, 里面包含了用戶的認證資訊和登錄狀態等資訊,而 Cookie 就是用戶通行證,
Token
Token 也稱作令牌,由uid+time+sign(+固定引數)組成:
? uid: 用戶唯一身份標識
? time: 當前時間的時間戳
? sign: 簽名, 使用 hash/encrypt 壓縮成定長的十六進制字串,以防止第三方惡意拼接
? 固定引數(可選): 將一些常用的固定引數加入到 Token 中是為了避免重復查庫
Token 的認證方式類似于臨時的證書簽名, 并且是一種服務器端無狀態的認證方式, 非常適合于 REST API 的場景. 所謂無狀態就是服務器端并不會保存身份認證相關的資料,
Token在客戶端一般存放于LocalStorage,Cookie,或SessionStorage中,在服務器一般存于資料庫中,
Token認證流程
Token 的認證流程與Cookie很接近
? 用戶登錄,成功后服務器回傳Token給客戶端;
? 客戶端收到資料后保存在客戶端;
? 客戶端再次訪問服務器,將Token放入Headers中;
? 服務器端采用filter過濾器校驗,校驗成功則回傳請求資料,校驗失敗則回傳錯誤碼,


Cookie,Session和Token的區別
Token可以抵抗CSRF攻擊,Cookie+Session不行
我們假設一個場景:
用戶正在登陸銀行網頁,同時登陸了攻擊者Tom的網頁;
銀行網頁未對CSRF攻擊進行防護;
Tom在網頁放了一個表單,該表單提交src為http://www.bank.com/api/transfer,body為count=1000&to=Tom,
如果用的是Session+Cookie,用戶打開網頁的時候就已經被Tom轉走卡里的錢了,因為form 發起的post請求并不受到瀏覽器同源策略的限制,因此可以任意地使用其他域的 Cookie 向其他域發送 post 請求,形成 CSRF 攻擊,在post請求的瞬間,Cookie會被瀏覽器自動添加到請求頭中,
但Token不同,Token是開發者為了防范CSRF而特別設計的令牌,瀏覽器不會自動添加到Headers里,攻擊者也無法訪問用戶的Token,所以提交的表單無法通過服務器過濾,也就無法形成攻擊,
分布式情況下的Session和Token
我們已經知道Session是有狀態的,一般存于服務器記憶體或硬碟中,當服務器采用分布式或集群時,Session就會面對負載均衡問題,
? 負載均衡多服務器的情況,不好確認當前用戶是否登錄,因為多服務器不共享Session,這個問題也可以將Session存在一個服務器中來解決,但是就不能完全達到負載均衡的效果,有辦法解決但是挺麻煩的,
而Token是無狀態的,Token字串里就保存了所有的用戶資訊
? 客戶端登陸傳遞資訊給服務器端,服務器端收到后把用戶資訊加密(Token)傳給客戶端,客戶端將Token存放于LocalStroage等容器中,客戶端每次訪問都傳遞Token,服務器端解密Token,就知道這個用戶是誰了,通過cpu加解密,服務器端就不需要存盤Session占用存盤空間,就很好的解決負載均衡多服務器的問題了,
注:這個方法叫做JWT(Json Web Token),
總結
? Cookie類似一個令牌,裝有SessionId,存盤在客戶端,瀏覽器通常會自動添加,
? Session存盤于服務器,可以理解為一個狀態串列,擁有一個唯一識別符號SessionId,通常存放于Cookie中,服務器收到Cookie后決議出SessionId,再去Session串列中查找,才能找到相應Session,同時Session依賴Cookie,
? Token可以說是一個無狀態的令牌,需要開發者手動添加,用戶資訊被加密到Token字串中,服務器收到Token后解密就可知道是哪個用戶,
? JWT只是一個跨域認證的方案,

撰寫
Eolinker:致力于API全生命周期開發管理的國產流行API工具,
參考文章
Cookie、Session、Token那點事兒
cookie,token驗證的區別
有了cookie為什么需要session
徹底弄懂session,cookie,token
CSRF Token的設計是否有其必要性
cookie,token,session三者的問題和解決方案
負載均衡集群中的session解決方案
JWT介紹
Json Web Token 入門教程
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/298855.html
標籤:其他
