JWT 和 Session 驗證比較
了解基於 Session 和 JWT 驗證的區別。探索取捨、優點和使用案例,為你的應用程序選擇合適的驗證方案。
一般來說,使用應用程序的第一步是驗證,即最終使用者提供身份憑證以成功登入。在此步驟之後,身份系統(即身份提供者、身份驗證服務器等)知道使用者是誰以及他們可以訪問哪些資源。
由於HTTP本質上是無狀態的,每個會話中的請求是獨立的,且不會記住先前請求的信息。為每個操作重新驗證用戶很麻煩且損害用戶體驗。
讓我們進入基於 Session 的驗證和JWT(JSON Web Tokens)驗證,這是兩種保持驗證狀態的流行方法。每種方法都有獨特的優勢和權衡,如何選擇取決於你的應用程序的具體需求。如果你在兩者之間決定,這個指南將提供幫助。
什麼是基於 Session 的驗證?
基於 Session 的驗證依賴於服務器來維護用戶的驗證狀態記錄。透過創建和管理會話,服務器使用戶不必在每次請求時都重新輸入憑證即可持續登入並與應用程序互動。
基於 Session 的驗證如何運作?
會話創建
- 用戶驗證並提供一些憑證(例如電子郵件和密碼)。
- 如果憑證有效,服務器將創建一個代表該會話的持久性記錄。會話包含的信息如隨機字符串、用戶標識符、會話開始時間、會話到期時間等。
SessionID
存儲在數據庫中,並作為Cookie返回給用戶的客戶端。
會話驗證
- 過程可以由用戶手動觸發(例如點擊選項卡、刷新頁面)或由客戶端自動觸發(例如在初始頁面加載期間或通過帶有
SessionID
的 API 調用)。 - 每個後續的呼叫從客戶端發送包含會話 Cookie的 HTTP 請求到服務器。
- 服務器通過查詢存儲在服務器上的會話數據驗證
SessionID
。 - 如果有效,服務器處理請求並授權用戶。
如何撤銷會話?
會話可以在實時中失效,在需要快速撤銷訪問的情況下非常方便。
- 用戶手動退出:服務器刪除會話記錄,有效地登出用戶。
- 管理員強制用戶登出:管理員或系統可以通過從數據庫中刪除特定會話來終止特定會話。例如,在安全洩漏期間。
- 會話過期:會話可以在一段不活動後自動過期,或在固定時間限制後過期。
基於 Session 的驗證的優點
- 簡單且可靠:會話記錄提供了清晰、集中化的來源,允許高程度的信任,並使授權決策更可靠。
- 實時撤銷:通過刪除或使會話記錄失效,可以快速撤銷用戶的訪問。
基於 Session 的驗證的缺點
- 分佈式系統中的延遲:在多台服務器間維護會話數據始終需要同步會話存儲。這會引入附加的延遲,因為服務器每次請求都必須檢查會話存儲。
- 高資源消耗:每個會話佔用服務器資源,當用戶基數擴大時影響性能。
- 安全風險:會話劫持(通過被竊取的會話 Cookie)可能准許未授權訪問用戶帳戶。
- 對 API 的使用有限:基於 Session 的驗證對移動應用程序不太理想。它在服務器上存儲會話數據,這麼多用戶時,可以增加負載和復雜性。此外,它使用 cookie,而在移動設備上更難處理。
什麼是 JWT 驗證?
JSON Web Tokens (JWTs) 採用了不同的方法,將所有相關的用戶信息直接嵌入到一個使用 JSON 對象的 Token 中。與基於 Session 的方法不同,JWT 是無狀態的,這意味著服務器不管理驗證記錄。
JWT 驗證如何運作?
一個 JWT 包含三個部分:header、payload 和 signature。
- header 包含簽名算法(例如,HS256)和 Token 的類型(JWT)。
- payload 包含核心claims,如用戶的身份、用戶角色和到期時間。
- signature 使用一個密鑰來簽名 header 和 payload,以便驗證簽名是否被篡改。
JWT 發行
- 客戶端將用戶憑證發送到身份驗證服務器(一個通用的身份提供者對於跨多個域管理訪問特別有用)
- 成功驗證後,服務器生成包含 header、payload 和 signature 的 JWT。
- AuthServer 將發行的 Token 發送給Client。客戶端儲存 JWT(例如,在 cookies、localStorage 或 sessionStorage 中)。
基於 Session 的工作流遵循類似的過程。然而,在驗證後,用戶信息存儲在服務器內的一個會話中,而 JWT 靠 tokens 被發送到客戶端來存儲和隨後使用。
Token 驗證
- 對於後續的 API 請求,客戶端在
Authorization
header 中發送 JWT(Bearer <token>
)。 - 服務器使用密鑰或公開密鑰驗證 JWT 的簽名並檢查其 claims(例如,到期時間、發行者)。
- 如果 Token 有效,服務器授予用戶訪問請求的資源。
基於 Session 的驗證要求服務器查詢一個會話存儲,特別是如果依賴於外部或集中式數據庫,這可能是緩慢的。與此相對,JWT 驗證是無狀態的,因為所有必要的信息都存儲在客戶端 Token 中,並使用簽名來確保安全。這消除了對會話管理的需求,使其在分佈式系統中更快速和更具可擴展性。
如何撤銷 JWT?
在客戶端,登出通常意味著清除本地會話並從存儲中移除 tokens(ID、訪問、刷新 token)。然而,對於 JWT 驗證,這僅意味著在本地登出用戶,集中式會話在授權服務器上保持不變。因此,除非 token 到期或被手動終止,否則用戶仍可能訪問相同會話下的其他應用。
撤銷 JWT(JSON Web Token)比基於 Session 的驗證更具挑戰性,因為 JWT 是無狀態的****並且無法在簽發後被無效,除非顯式實施特定策略。常見方法包括:
- 短到期時間:為 JWT 設置一個短的
exp
claim(例如 15 分鐘)。一旦到期,用戶必須重新驗證。如果 token 被盜用,風險就減少了,因為攻擊者只能在有限的時間使用它。為了維持連續的用戶體驗,可以使用刷新 token來最小化重新驗證的麻煩。 - Token 黑名單:在關鍵情況下(例如用戶登出、密碼更改),維護一個撤銷的 Token 黑名單。服務器檢查傳入的 tokens 是否匹配這個黑名單,並拒絕任何匹配。雖然有效,但這個方法需要跟踪撤銷的 Token,這與 JWT 的無狀態性質相矛盾,且如果列表太大,效率會下降。
- 回叫端點:在授權服務器上設置一個回叫端點,來使 tokens(例如刷新 tokens)無效。一旦刷新 token 被撤銷,由其簽發的任何訪問 tokens 將不再被續簽。這種方法在OAuth2流程中很好地運作。
JWT 驗證的優點
- 快速且信息豐富:JWTs 的自包含特性使客戶端側驗證更加快速和高效,無需服務器互動。它們還可以在 Token 中包含自定義 claims(例如用戶角色或其他相關數據),使服務器可以在不查詢數據庫的情況下確定角色。
- 增強的安全性:JWTs 使用簽名和加密技術,使攻擊更困難。
- 跨域支持:JWTs 非常適合SOS (Single Sign-On)和跨域驗證。它們允許用戶在多個域或服務間使用相同的 Token 驗證。
- 適合移動設備:JWTs 對於需要無狀態驗證的移動應用程序效果很好。Token 可以儲存在客戶端,並隨每個請求一起發送,提高效率和使用便捷性。
JWT 驗證的缺點
-
JWT 無法實時更新
一旦 JWT 被簽名,它無法被撤銷或更新,只要簽名有效並且未到期,就會被認為是有效的。
如果用戶的訪問權限發生變化(通常是降級),用戶將仍會擁有被移除的訪問資源的權限,直到 JWT 過期。類似地,如果 JWT 包含基於角色的授權信息,新授權範圍將在舊的 JWT 過期後生效。換句話說,JWTs 不適合即時撤銷,用戶可以設置適當的到期時間來緩解這個問題。
-
多設備與撤銷困境
在 JWT 過期前無法驗證所有已發行的 JWTs 來實施用戶對所有設備的撤銷。盡管從理論上可以撤銷簽名密鑰來使所有使用該密鑰的 JWTs 失效,這也會使所有使用該密鑰的 JWTs 失效,處理緩存密鑰的過程會使這種方法對單純的用戶撤銷操作不具實際操作性。
一些身份提供者可能擁有針對這些 JWT 問題的預製解決方 案。欲獲得更多信息,請檢查“改進 JWT 驗證體驗的最佳實踐”。
JWT 和 Session 的區別是什麼?
Session 和 JWT 是兩種為在無狀態的 HTTP 環境中保持驗證和授權上下文的流行方法。儘管這兩種方法各有優缺點,它們提供不同的效益和缺憾。
Sessions 為單個請求授權提供了更强的保證,並且更容易安全地實施。然而,它們對服務器端數據庫驗證的依賴引入了延遲開銷,這可能消極地影響高響應的應用程序的用戶體驗。
另一方面,JWTs 對於更快速的授權和與外部應用的互操作性是有利的,但需要更多的開發者努力來解決安全性複雜問題。例如,我們可以使用 Webhook 來通知客戶端用戶的訪問被撤銷,這樣客戶端可以清除緩存的 JWT 並迫使用戶重新驗證。
由於基於 Token 的驗證更適合擴展,儘管仍然具有可管理的局限性,越來越多的現代應用程序開始採用它。
Session 與 JWT:選擇合適的方法
你的驗證方法應該符合應用程序的架構和特定需求。以下是選擇的快速指南:
何時使用基于 Session 的驗證
當需要即時會話控制,需要集中管理或可擴展性不是主要關注點時,基於 Session 的驗證最適合。以下是它的優勢所在:
-
擁有持久會話的 web 應用
對於網上購物網站等平台,會話是追踪用戶、購 物車和瀏覽偏好的關鍵。
-
需要即時會話控制的應用程式
如銀行或金融服務等應用受益於服務器控制的會話數據,以確保強健的訪問管理和安全性。
-
單服務器或小型系統
在內部工具或不需要重度可擴展的小型應用中,簡單的會話管理有助於提高易用性和可靠性。
何時使用 JWT 驗證
JWT 驗證更適合優先考慮可擴展性、效率和分佈式系統的應用程式。它對於客戶端與服務器的無狀態交互尤其有用。考慮在以下情況使用基於 Token 的驗證:
-
單一登入 (SSO)
JWTs 非常適合單一登入,即用戶驗證一次即可無縫訪問使用相同 Token 的多個服務或應用。分享一篇關於使用 OAuth 2.0 與 OIDC 保護雲端應用的詳細說明,並為訪問 Tokens和ID Tokens使用 JWT 格式。
-
移動應用程序
移動應用通常偏好使用 JWTs 進行驗證,因為 tokens 可以安全地存儲在設備上並隨每個 API 請求一起發送。探索快速整合 JWT 驗證到 Android / iOS。
-
微服務架構
在微服務環境中,JWTs 使每個服務能夠獨立驗證 Token,而不依賴於中央的會話存儲,確保可擴展性和效率。
-
跨域驗證
JWTs 在涉及多個域或子域(例如
api.example.com
、dashboard.example.com
和docs.example.com
)的情況下特別出色。與 Cookies 不同,JWTs 允許跨域驗證而無需附加依賴。 -
APIs 和 Web Services
RESTful APIs 和 Web 服務通常使用 JWTs 進行驗證,因為它們輕量、可攜帶,且消除了服務器端會話管理的需要。了解更多關於機對機驗證的狀況,適用於你的應用需要與資源直接通訊的情況。
改善 JWT 驗證體驗的最佳實踐
JWT 驗證是個好工具,但它可能帶來影響用戶體驗的挑戰。Logto 提供了一個簡單而可靠的解決方案來克服這些困境,使其成為安全且高效的驗證的首選。
使用 JWT 處理用戶登出問題
JWT 驗證的一個常見問題是確保適當的用戶登出體驗。Logto 的開箱即用 SDK 簡化了這一過程。
- 通過在客戶端側清除 Tokens 和本地會話並將用戶重定向到 Logto 的 end session endpoint,你可以輕鬆終止客戶端應用和服務器兩者上的會話。
- 此外,Logto 支援 back-channel logout,允許 AuthServer 通知共享相同會話的所有客戶端應用用戶登出時。
這確保了你生態系統中的一致且安全的會話管理。了解如何處理用戶登出。
處理用戶權限更改
使用 JWT 管理用戶權限即時更改也可能很棘手。由於 JWTs 的無狀態設計,任何更新過的權限或角色在 Token 到期前都可能不會生效。Logto 提供了有效處理這一問題的策略:
- 對於此用戶的權限減少:使用短訪問 Token 到期時間或動態通過 API 調用驗證權限。
- 對於此用戶添加新權限:更新 AuthServer 以包括新的權限範圍並重新同意用戶以應用這些更改。
這些解決方案有助於保持權限最新,並確保系統更安全且更具回應性。了解如何處理權限更改。