登錄認證是任何系統中避不開的一個話題,登錄認證隨著系統架構的演變而出現與架構相適應的方案。下面介紹架構演變過程中登錄常客Cookie、Session、JWT之間的關系。
1、單體架構
![](http://image.uc.cn/s/wemedia/s/upload/2024/151c1ffcb936dabb3ea2639e31c398c5.jpg)
單體架構階段下,前端代碼和後端代碼都在一個項目中,也就不存在跨域問題。此時的登錄認證機制采用的是Cookie和Session的方式進行。認證的方式如下:
![](http://image.uc.cn/s/wemedia/s/upload/2024/b2fc1883358a73e2c5b8e41d83e96c0d.jpg)
用戶訪問的服務器的時候,攜帶服務器給予的sessionId到後端,後端拿到sessionId之後就可以拿到登錄用戶的信息。
2、前/後端分離
單點的架構中前端和後端代碼都在一個項目中,對開發人員的開發、業務部署都帶來了阻力,于是就出現了前後端分離模式,如下的前後端分離模式圖:
![](http://image.uc.cn/s/wemedia/s/upload/2024/357ecbc0d58c0e5a0269e27424707d7e.jpg)
前後端分離模式中出現了跨域問題,跨域使得浏覽器和服務器數據交互受到阻礙,並且也無法獲取Cookie中的sessionId了。如果想要通過Cookie和Session方式來實現登錄認證,那麽就要解決跨域問題,此時就有了跨域資源共享(CORS)。CORS的流程如下:
![](http://image.uc.cn/s/wemedia/s/upload/2024/44472f168f5debd8645c1162bead0bb7.jpg)
通過CORS解決了跨域問題之後,登錄認證的方式繼續使用Cookie和Session方式來完成。
3、分布式系統
![](http://image.uc.cn/s/wemedia/s/upload/2024/703f00e5d01e6cce50e2a5f288536d34.jpg)
隨著業務發展的發展,單個系統拆分成多個子系統並且子系統部署多台服務,此時的服務與服務之間的session是不共享的,如果想要采用cookie和session方式實現登錄認證功能,那麽就要解決session共享的問題。
業界主流使用的是單點登錄來解決分布式下的session共享問題,其流程如下所示:
![](http://image.uc.cn/s/wemedia/s/upload/2024/2d502d2844d9cd504b817ccbff13339f.jpg)
(1)用戶請求訂單服務的時候,訂單服務發現其沒有登錄,于是請求認證中心進行認證。
(2)認證中心彈出登錄頁讓用戶填寫賬號和密碼,認證系統對其賬號與密碼進行驗證,驗證通過之後把登錄狀態寫入SSO的session中,同時浏覽器也會寫入SSO的Cookie中。
(3)SSO登錄系統完成以後生成ticket,然後跳轉到訂單服務上,同時把ticket作爲參數傳遞給訂單服務上,訂單服務拿到ticket後從後台向SSO發送請求來驗證ticket是否有效,驗證通過後訂單服務把登錄狀態寫入到session中並設置訂單服務域下的Cookie。
通過以上的步驟就實現了跨域的單點登錄,後面再訪問訂單服務的時候,訂單服務上就是登錄狀態。
(4)用戶此時想訪問商品服務,商品服務沒有登錄就會跳轉到SSO上,由于SSO在用戶訪問訂單服務的後已經是登錄狀態了,所以不需要重新登錄驗證。
(5)SSO會生成ticket給商品服務,浏覽器會跳轉到商品服務上並把ticket作爲參數傳遞給商品服務,商品服務拿到ticket後再去後台訪問SSO驗證ticket的有效性,SSO驗證通過後商品服務把登錄狀態寫入session中並在浏覽器中寫入商品域的Cookie。
下面介紹一種使用Redis和Cookie實現的單點登錄的設計方案,具體的實現流程圖如下所示:
![](http://image.uc.cn/s/wemedia/s/upload/2024/88f2bcb47acb356afa93dfca33418a22.jpg)
4、分布式系統下的去中心化認證
Cookie和Session機制、Cookie和Redis機制都需要服務器需要維護一個會話或者組件來標識這些用戶已經登錄;那麽是否存在一種認證方式直接就可以從請求中知道這個用戶是哪個人呢?由于就出現了無狀態登錄,典型的實現方案是JWT機制,JWT機制的工作原理如下:
![](http://image.uc.cn/s/wemedia/s/upload/2024/d5684b658cceeabceaf9ca95e9987c09.jpg)
無狀態登錄最大的優勢在于系統的水平擴展性強,因爲服務器不需要維護每個用戶的登錄信息,所以可以非常方便的爲這個集群增加實例。
無狀態登錄的最大問題就是沒有辦法注銷,一旦令牌頒發出去了,除非令牌自己過期了否則令牌會一致有效,所以設計中需要增加Redis來輔助實現強制的注銷的功能。
總結:
(1)Cookie和Session機制是實現登陸認證的基本方式,隨著系統的不斷演變,于是單體架構下的這套認證機制失效了,爲了適應這套認證流程出現了不同的解決方案來保證認證流程正常的使用。
(2)Cookie和Session機制是有狀態的登陸,爲了適應一些特定的場景,出現了無狀態登陸機制(JWT)。