動態

詳情 返回 返回

[登錄鑑權] cookie、session和token的實現和區別 - 動態 詳情

前言:
本文中的用户端(client)約等於瀏覽器。
服務端就是sever。

cookie、session、token都是由sever生成,保存在client端。
三者最大的不同在於服務端對cookie、session、token的處理。

cookie
1、在client輸入賬號密碼,點擊登錄發送請求 a到sever,sever驗證賬號密碼通過,獲知用户信息。
2、這個時候sever生成cookie,在請求a的response中用Set-Cookie字段把cookie信息返回給發送請求的client。client見到Set-Cookie之後把cookie記錄在本地。
3、client再次發送請求b的時候會攜帶cookie,讓sever知道這個請求的發起者的身份(或者權限)。

session
1、在client輸入賬號密碼,點擊登錄發送請求 a到sever,sever驗證賬號密碼通過,獲知用户信息。
2、這個時候sever生成有對應關係的key和value。value中保存用户信息(下文用userMessage指代),userMessage需要存儲在服務器端(一般是保存在內存數據庫中,這樣查的快)。key是一長串無序字符串,這裏的key(下文用sessionString指代)就是session。
3、sessionString作為cookie的一部分發送給client,cookie的內容中由sever添加一個特殊的字段(字段名可以是session、sessionId、sys_session等等),這個字段用於傳輸和存儲sessionString(舉例: 特殊字段名a_sys_session 對應 sessionString) 。
在請求a的response中用Set-Cookie字段把cookie信息返回給發送請求的client,client見到Set-Cookie之後把cookie記錄在本地,a_sys_session和sessionString也被記錄在本地。
4、client再次發送請求b的時候會攜帶cookie,cookie中又有a_sys_session字段,當sever拿到cookie後,從cookie中提取出a_sys_session字段對應的sessionString。
5、通過sessionString查詢userMessage,獲取用户信息(也有可能查詢不到,如過期了,或者sessionString被改了)。獲取用户信息之後,sever知道這個請求的發起者的身份(或者權限)。

image.png

token
1、在client輸入賬號密碼,點擊登錄發送請求 a到sever,sever驗證賬號密碼通過,獲知用户信息。
2、sever將用户信息(下文用userMessage2指代)拿出來格式化為一種特定的格式(如string、object)。sever自身需要有一個秘鑰(下文用secretKey指代),這個秘鑰保存在服務器端,將userMessage2和secretKey通過加密算法(createFunction)生成一段新的字符串(下文用secretString2指代)。將userMessage2和secretString2通過某種易拆分的方式加工成一個新字符串(concatString2),這裏的concatString2就是token。sever端無需保存token。
3、concatString2需要返回給client,這時是有兩種方式可選的。
3.1其一是作為cookie的一部分發送給client。cookie的內容中由sever添加一個特殊的字段(字段名可以是token、sys_token等等),這個字段用於傳輸和存儲concatString2(舉例: 特殊字段名a_sys_token對應 concatString2) 。
在請求a的response中用Set-Cookie字段把cookie信息返回給發送請求的client,client見到Set-Cookie之後把cookie記錄在本地,a_sys_token和concatString2也被記錄在本地。client再次發送請求b的時候會通過cookie攜帶token信息。

3.2其二是作為特定的返回字段交給client自行存儲。這種情況下token需要在客户端接收到請求a的response之後用程序實現將token存儲到sessionStorage或localStorage中。另外每次發送請求時都需要將token攜帶上,傳遞給sever。這種情況下攜帶token信息的方式的通用做法是將token放在請求頭的Authorization字段。

4、client再次發送請求b的時候攜帶token信息到達sever後,sever解析得到concatString2,再通過concatString2拆分出userMessage2和secretString2。
5、通過解析得到的userMessage2加上服務端保存的secretKey+createFunction重新生成newSecretString,校驗newSecretString和secretString2是否一致。如果校驗通過,則確認userMessage2是正確的用户信息。

三者安全性對比:
cookie的安全性最差,因為cookie把用户信息放在了本地,可能會被修改。雖然我們可以通過設置httpOnly禁止通過js代碼改動cookie,但如果從瀏覽器中複製cookie,再修改cookie用http工具(如postman)發送請求,是有可能獲取到額外的信息的。
session把用户信息存儲在的sever端,token有校驗的過程,兩者的安全性遠強於cookie。session和token的安全性在同一級別,硬要分個高下我感覺session稍強。但要説能改token的信息,那必須同時獲知創建token的secretKey和createFunction,這也得是有內鬼才行吧。

session和token的優劣勢分析:
由於sever可能對接大量的client,也就需要存放大量的 session,這樣會導致數據庫的IO壓力,要考慮用户數量。此外如果服務器端是一個集羣,為了同步登錄態,需要將 session 同步到每一台機器上,無形中增加了sever的維護成本。
token的優勢在於服務器端不需要存儲token,所以不會對服務器端造成額外的存儲壓力,即使是服務器集羣,也不需要增加維護成本。
token的實現方式較為靈活,前端有很多發揮空間,不一定要保存在Cookie 中。
token 下發之後,只要在生效時間之內,就一直有效,如果服務器端想收回此 token 的權限,並不容易。(token的做法我沒實踐過,不知道有什麼方式可以收回token權限,盲區)

完結。

同步更新到自己的語雀
https://www.yuque.com/diracke...

user avatar linx 頭像 heath_learning 頭像 sy_records 頭像 windseek 頭像 baozouai 頭像 mi2nagemao 頭像 zaoying 頭像 axuicn 頭像 shine_zhu 頭像 wdllmh 頭像 jackzhoumine 頭像 shumin_5bd11c2a4b889 頭像
點贊 18 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.