在上一篇文章我們聊完了授權的過程,在服務器對客戶端完成授權之后,服務器會給客戶端頒發對應的憑證,客戶端持有該憑證訪問服務端,服務器便能知道你是誰,你有什么權限等信息。這一章我們具體聊聊常見的憑證管理技術有哪些。
在軟件架構中,關于憑證如何存儲和傳遞,一直有兩種不同的解決思路,兩種不同的解決方式,實際上反映了兩種不同的架構思路:
在互聯網早期,這個問題早就有了明確的答案。大多數應用都采用了 “Cookie-Session” 的方法,這種方法通過在服務器上存儲用戶狀態,來實現用戶身份的識別和信息的傳遞。這種方法在很長一段時間里都是主流。
然而,隨著微服務和分布式系統的興起,我們發現由于 CAP 的限制,服務器端存儲狀態信息的方式開始面臨很多問題(微服務要求服務端本身是無狀態,才能實現動態擴縮容)。這就迫使我們重新考慮被放棄的客戶端狀態存儲方法。在這個背景下,JWT(JSON Web Token)的令牌的方案開始受到關注。JWT 是一種在客戶端存儲用戶狀態信息的方式,它允許用戶在不同的服務器之間自由切換,而不需要重新登錄。這種特性在分布式系統中非常有用。但是要明白,JWT 和 Cookie-Session 只是對授權信息存儲的主體(客戶端,服務端)不同,各有優勢,合適場景不同,不存在誰比誰要先進的問題。在本節中,我們將探討 Cookie-Session 和 JWT 兩種方案的相同點和不同點,幫你更好地理解這兩種方案的優缺點,以及它們在不同場景下的應用。
總所周知,因為 HTTP 是無狀態協議,所以 Cookie-Session 的原理其實很簡單,就是解決 HTTP 協議無狀態的問題,在 RFC 6265 中定義了 HTTP 的狀態管理機制,增加 Set-Cookie 指令,服務端向客戶端發送一組信息(標識)示例:
HTTP/1.1 200 OKContent-type: text/htmlSet-Cookie: session_token=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Path=/
客戶端收到指令后在此后一段時間的 HTTP 請求中都發給服務端會話信息(在 Header 中攜帶 cookie 信息),以便服務器區分不同的客戶端:
GET /profile HTTP/1.1Host: www.example.comCookie: sessionid=xyzasdzxc123789456
客戶端的 Cookies 里通常只存儲一個無意義,不重復的字符串,通常命名是 sessionid 或 jessionid ,服務端則根據該字符串作為 Key,和用戶信息建立關聯后存儲在服務端的內存或者緩存中。再輔以一些超時自動清理的措施來管理會話。
它們的交互過程如下:
圖片
這種服務端的狀態管理機制就是 Session,Cookie-Session 也是最傳統,但今天依然廣泛應用于大量系統中的,由服務端與客戶端聯動來完成的狀態管理機制。
cookie-session 的方案在存儲授權信息具有以下優勢:
Cookie-Session 在單體服務環境中是最合適的方案,但是因為服務端有狀態,當需要水平擴展服務能力,要部署集群時就開始面臨麻煩了。接下來的 JWT 令牌就是 Cookie-Session 在分布式環境的替代品,但是不能說 JWT 要比 Cookie-Session 更加先進,更不可能全面取代 Cookie-Session 機制。
當服務端有多臺,并且不能存儲狀態的時候,客戶端就要承擔存儲有狀態(授權信息)的職責了。這就是 JWT 令牌的方案思路。
JWT(JSON Web Token)是一種定義在 RFC 7519 標準中的令牌格式,主要應用于現代分布式應用系統中,經常與 OAuth2 協議配合使用。在深入探討 JWT 的結構之前,我們先來直觀地了解一下它的基本形式。示例:
圖片
注意:JWT 令牌不加密,只使用 Base64URL 轉碼,所以 JWT 令牌里別放敏感信息,令牌只解決防篡改的問題,并不解決防泄漏的問題,JWT 令牌都可以在 JWT 官網(https://jwt.io)上進行解碼。如圖所示,JWT(JSON Web Token)由三部分組成:Header(頭部)、Payload(負載)、Signature(簽名)。這三部分之間使用點(.)分隔。
Header:Header 部分通常包含令牌的類型(通常是 JWT)和使用的加密算法,例如 HS256:
{ "alg": "HS256", "typ": "JWT"}
Payload:Payload 部分包含所需的聲明,這些聲明可以包括用戶信息或其他相關數據。例如,用戶ID和過期時間:
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022, "exp": 1516242622}
負載部分,JWT 在 RFC 7519 中推薦(非強制約束)了七項聲明名稱(Claim Name),如有需要用到這些內容,建議字段名與官方的保持一致:
此外在 RFC 8225、RFC 8417、RFC 8485 等規范文檔,以及 OpenID 等協議中,都定義有約定好公有含義的名稱,可以參考 IANA JSON Web Token Registry。
Signature:Signature 是使用 Header 中指定的算法和一個密鑰對 Header 和 Payload 進行簽名得到的。對前面兩部分內容進行加密計算,以例子里使用的 JWT 默認的 HMAC SHA256 算法為例,將通過以下公式產生簽名值:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload) , secret)
簽名的意義在于確保負載中的信息是可信的、沒有被篡改的,也沒有在傳輸過程中丟失任何信息。因為被簽名的內容哪怕發生了一個字節的變動,也會導致整個簽名發生顯著變化。JWT 默認使用的 HMAC SHA256 算法是一種密鑰哈希算法,適用于單體應用中,因為加密和驗證都需要由同一授權服務完成。在多方或分布式應用中,通常使用非對稱加密算法進行簽名。這種情況下,授權服務使用私鑰簽名,并通過遵循 JSON Web Key 規范公開一個公鑰。這個公鑰用于驗證簽名,使其他服務能夠獨立驗證 JWT 的真實性,無需直接與授權服務通信。
JWT 令牌的交互流程如下:
圖片
說明:如果是在分布式環境下,通常會有單獨的認證服務器來負責頒發令牌。
按照 HTTP 協議的規范,客戶端可以通過多種方式使用 HTTP 協議發送 JWT 令牌給服務端。最標準的方式是將 JWT 放在 HTTP 的 Authorization 頭部中,通常與 Bearer 方案一起使用。這種方法簡單且符合 RESTful API 的最佳實踐:
GET /api/resource HTTP/1.1Host: example.comAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIx......
JWT 令牌是分布式系統下憑證載體的優秀解決方案,它優點眾多:
但是沒有完美的解決方案,cookie-session 的優點也 JWT 也缺點:
本文鏈接:http://www.www897cc.com/showinfo-26-85860-0.html憑證管理揭秘:Cookie-Session 與 JWT 方案的對決
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
下一篇: 大廠的OLAP架構啥樣的?