幹掉服務狀態!從 Session 到 Token,複雜度降低100倍

轉載:https://mp.weixin.qq.com/s/UzO9Jp79RqGSSMP5GzbVxw

在講Token之前,先簡單說說什麼是 Session 和 Cookie。

首先要知道 HTTP 請求是無狀態的;

無狀態的意思就是:每一次請求都是獨立的;每一次請求不會受到前面請求的影響,也不會影響後面的請求;

比如我們登錄一個系統的時候,驗證用戶名密碼之後,打開系統各個頁面的時候就不需要再進行登錄操作了,直到我們主動退出登錄或超時退出登錄;為了讓服務器有“記憶功能”,我們可以用到 Session、Cookie。

1、Cookie

是在客戶端(瀏覽器)保存用戶信息的一種機制;Cookie 由服務器生成,發送給瀏覽器,然後瀏覽器把 Cookie 以鍵值對的形式保存在客戶端的某個目錄下面;每種瀏覽器存儲大小會有一些差異,一般不超過 4KB;

當下一次請求的時候,會把 Cookie 發送給服務端,服務端對 Cookie 中的信息解析並驗證身份。

比如你入職一個公司,會給你辦一張工卡,上面有你的姓名、工號、部門等信息,你進入職場的時候,拿著工卡就可以進出。

但是 Cookie 是不可以跨域名使用的;就好像我拿著我們公司的工卡,去你們公司,保安肯定是不會放我進去的。

2、Session

保存在服務端,可以用於記錄客戶狀態;

比如我們經常會用 Session 保存客戶的基本信息、權限信息等;用戶第一次登錄之後,服務器就會創建一個 Session ,並將 SessionID 返回給瀏覽器,瀏覽器通常將其寫入到 Cookie 中,這種 Cookie 也叫做 SessionCookie ,瀏覽器再次訪問時,只需要拿著 SessionID 從服務端查找 Session 就可以了。

另外,這個 SessionID 不一定非要保存到 Cookie 中,只是對於瀏覽器客戶端,大家的默認做法是放在 Cookie 中。

3、Cookie 和 Session

關於 Cookie 和 Session 的區別,很多同學會回答:“Cookie 保存在客戶端,Session 保存在服務器端”,其實這樣的想法並不全面:

Cookie 是一個實際存在的的東西,一個很具體的東西,就是一段數據,而 Session 是一個抽象概念,或者叫做模式方法,它有很多實現方案;

比如 Tomcat 的實現方法:把狀態保存在服務端,然後生成一個 JSESSIONID 放在 Cookie 中;請求過來之後,拿著 JSESSIONID 在服務器端查詢並驗證狀態。

幹掉服務狀態!從 Session 到 Token,複雜度降低100倍

4、Token

當然,隨著用戶量的增加,保存在服務端的 Session 也不斷增加,這給服務端帶來了很大的壓力,並且如果程序是集群或分佈式方式部署,同一個用戶第一次請求,訪問到了 A 服務器,創建了 Session,但是第二次請求卻發到了 B 服務器上,但是 B 服務器上並沒有之前創建的 Session;這就是分佈式架構中的 Session 共享問題。

針對這個問題,我們可以進行服務器之間的 Session 同步,或者乾脆把 Session 保存到第三方的組件中,例如保存到 Redis 中;但是不管是哪種方案,都讓 Session 變成了項目的負擔。

這時候,服務端就會想,如果 Session 不保存在我這裡多好,第一次發送用戶名密碼給我,驗證通過後我給你一個通行證,以後客戶端每次請求的時候就帶著這個通行證;

這個通行證就是 token,當然這個驗證結果中需要包含客戶端信息,服務端需要知道請求是誰發過來的;還需要包含時間信息,因為通行證不可能永遠有效;通行證還不能是明文的,否則會有被截獲的風險。

HMAC-SHA1:

token = user_id|expiry_date|HMAC(user_id|expiry_date, k)

AES:

token = AES(user_id|expiry_date, x)

RSA:

token = RSA(user_id|expiry_date, private key)

幹掉服務狀態!從 Session 到 Token,複雜度降低100倍

5、SSO 單點登錄

有些公司會建設統一登錄系統(單點登錄),客戶端先去這個系統獲取 Token ,驗證通過再拿著這些Token去訪問其他系統;API Gateway 也可以提供類似的功能,我們公司就是這樣,客戶端接入的時候,先向網關獲取 Token,驗證通過了才能訪問被授權的接口,並且一段時間後要重新或者 Token。

幹掉服務狀態!從 Session 到 Token,複雜度降低100倍

6、Token 和 Session

對於 session 和 token ,對比它們沒有本質的區別,兩者都是加密後的字符串,都可以做身份驗證。當然 token 比 session 還是有一定區別的,比如 token 跨域更容易,token 更好控制等等,另外在授權場景下,token 比 session 有著更大的優勢;

比如,我開發一個網站,允許微信用戶登錄,使用 token 的流程大概是這樣的:

  • 登錄網站時,跳轉到微信登錄頁面;
  • 用戶輸入用戶名密碼登錄微信後,給我們一個 token;
  • 用戶拿著 token 就可以在我們的網站使用,而我們網站並不需要知道你微信的用戶名和密碼。

總之,如果在同一個網站內,token 和 session 並沒有太大的區別,如果跨站使用,token 會更方便一些。

Cookie、Session 和 Token 就介紹這麼多,大家有問題可以留言一起討論!


分享到:


相關文章: