繁體中文(香港)
  • jwt
  • authentication
  • session
  • token
  • revoke jwt

JWT 與 Session 驗證

了解基於 Session 和 JWT 驗證的差異。探索權衡、優勢和使用情境,以便為你的應用選擇合適的驗證方案。

Ran
Ran
Product & Design
Darcy Ye
Darcy Ye
Developer

一般來說,使用應用程式的第一步是身份驗證,此時最終用戶提供身份證明來成功登入。完成此步驟後,身份系統(即身份供應商、驗證伺服器等)就可以知道用戶是誰以及他們可以訪問哪些資源。

由於HTTP 本質上是無狀態的,因此會話中的每個請求都是獨立的,不會回憶前一個請求的信息。重新驗證用戶的每個操作都是繁瑣的,並且會損害用戶體驗。

我們來看看基於會話的驗證JWT(JSON 網路令牌)驗證,這是維持驗證狀態的兩種流行方法。每種方法都有其獨特的優勢和權衡,選擇它們取決於應用的具體需求。如果你正在決定使用哪一種,這篇指南將幫助你。

什麼是基於會話的驗證?

基於會話的驗證依賴於伺服器來維持用戶的驗證狀態記錄。通過創建和管理會話,伺服器使用戶能夠保持登入狀態,並繼續與應用程式進行交互,而不必在每個請求中重新輸入憑據。

基於會話的驗證如何運作?

會話創建

  1. 用戶進行驗證並提供一些憑據(例如,電子郵件和密碼)。
  2. 如果憑據有效,伺服器會創建代表該會話的持久記錄。會話包含的信息如隨機字串、用戶標識符、會話開始時間、會話過期時間等。
  3. SessionID 被存儲在數據庫中,並以cookie 的形式返回到用戶的客戶端

會話驗證

  1. 此過程可以由用戶手動觸發(例如,點擊標籤,刷新頁面)或由客戶端自動觸發(例如,初始頁面加載或通過 API 調用帶有 SessionID)。
  2. 每個後續的調用都會從客戶端伺服器發送一個包含會話 cookie 的 HTTP 請求。
  3. 伺服器通過查閱存儲在伺服器上的會話數據來驗證 SessionID
  4. 如果有效,伺服器處理請求並授權用戶。

如何撤銷會話?

會話可以實時失效,這在需要快速撤銷訪問的情況下很方便。

  • 用戶手動登出:伺服器刪除會話記錄,有效地將用戶登出。
  • 管理員強制用戶登出:管理員或系統可以通過從數據庫中刪除特定會話來終止該會話。例如,在安全漏洞期間。
  • 會話過期:會話在一段不活動時間後自動過期,或者有固定的時間限制。

基於會話驗證的優點

  • 簡單可靠:會話記錄提供了明確的集中來源,允許高度信任,並使授權決策更加可靠。
  • 實時撤銷:通過刪除或使會話記錄失效,可以快速撤銷用戶的訪問權限。

基於會話驗證的缺點

  • 分佈式系統中的延遲:跨多個伺服器維持會話數據總是需要同步會話存儲。這會引入額外的延遲,因為伺服器在每次請求時都需要檢查會話存儲。
  • 高資源消耗:每個會話都會佔用伺服器資源,會影響用戶基數擴展時的性能。
  • 安全風險:會話劫持(通過偷取會話 cookie)可以允許未經授權的訪問用戶帳戶。
  • 對 API 的有限使用:基於會話的驗證對移動應用程式而言並不理想。它將會話數據存儲在伺服器上,當有許多用戶時,這會增加負載和複雜性。此外,使用 cookie,也很難在移動設備上操作。

什麼是 JWT 驗證?

JSON 網路令牌(JWT) 通過將所有相關用戶信息直接嵌入令牌,使用 JSON 對象的方式採取不同的方式。不像基於會話的方法,JWT 是無狀態的,即伺服器不管理驗證記錄。

JWT 驗證如何運作?

JWT 包含三個部分:headerpayloadsignature

  • header 包含簽名算法(例如,HS256)和令牌類型(JWT)。
  • payload 包含核心claims,例如用戶的身份、用戶角色和過期時間。
  • signature 使用密鑰對 header 和 payload 進行簽名,允許驗證簽名是否已被篡改。

image.png

JWT 發行

  1. 客戶端將用戶憑據發送到驗證伺服器(一個通用的身份供應商尤其有助於管理跨多個域的訪問)。
  2. 驗證成功後,伺服器生成一個包括 header、payload 和 signature 的 JWT。
  3. AuthServer 向客戶端發送已發行的令牌。客戶端將 JWT 儲存(例如,在 cookies、本地存儲或 sessionStorage 中)。

基於會話的工作流程遵循類似的過程。然而,經過身份驗證之後,使用者信息會被儲存在伺服器上的會話中,而 JWT 則依賴於發送給客戶端以供儲存和後續使用的令牌。

令牌驗證

  1. 對於後續的 API 請求,客戶端在 Authorization header 中發送 JWT(Bearer <token>)。
  2. 伺服器使用一個秘密或公鑰驗證 JWT 的簽名,並檢查其 claims(例如,過期時間,發行者)。
  3. 如果令牌有效,伺服器允許客戶端訪問所需的資源。

基於會話的驗證要求伺服器查詢會話存儲,這可能會很慢,尤其是當它依賴於外部或集中的數據庫時。相反,JWT驗證是無狀態的,所有必要的信息都存儲在客戶端的數據標籤中,並使用簽名來確保安全性。這消除了會話管理的需求,特別是在分佈式系統中,使其更快和更具擴展性。

如何撤銷 JWT?

在客戶端,登出通常意味著清除本地會話並從存儲中刪除令牌(ID、訪問、刷新令牌)。然而,對於 JWT 驗證,這只是在本地登出了用戶,並未刪除授權伺服器上的集中會話。結果是,只要令牌未過期或未被手動終止,用戶可能仍然可以訪問其他應用。

撤銷 JWT 比基於會話的驗證更有挑戰,因為 JWT 是無狀態的,一旦發行就不能被無效化,除非採取具體的策略。常見的方法包括:

  • 短過期時間:為 JWT 設置一個短的 exp claim(例如,15 分鐘)。一旦過期,用戶必須重新驗證。如果令牌被泄露,此方法可降低風險,因為攻擊者只能在有限時間內使用它。為了保持無縫的用戶體驗,可以使用刷新令牌 來降低重新驗證的麻煩。
  • 令牌黑名單:對於重要情況(例如,用戶登出,密碼變更),應維護一個撤銷令牌的黑名單。伺服器將檢查傳入的令牌是否在此黑名單上,並拒絕任何匹配的令牌。雖然有效,但這種方法需要跟踪被撤銷的令牌,這與 JWT 的無狀態本質相違背,列表增長大時也可能變得沒有效率。
  • 撤銷端點:在授權伺服器上引入開工撤銷端點,令牌(例如,刷新令牌)可以被無效化。一旦刷新令牌被撤銷,任何用它發出的訪問令牌將不再可以被續簽。這種方法在OAuth2 流程中效果良好。

JWT 驗證的優點

  • 快速且信息豐富:JWT 的自我封裝特性使得客戶端驗證更快、更高效,無需伺服器交互。它們還可以包括自定義 claims(例如,用戶角色或其他相關數據),使伺服器可以不查詢數據庫就確定角色。
  • 提高安全性:JWT 使用簽名和加密技術,使攻擊更加困難。
  • 跨域支持:JWT 是單點登入(SSO) 和跨域驗證的完美選擇。它們允許用戶使用相同的令牌跨多個域或服務進行驗證。
  • 移動友好:JWT 對需要無狀態驗證的移動應用程式非常有效。令牌可以存儲在客戶端,並以每個請求發送,增強了效率和易用性。

JWT 驗證的缺點

  • JWT 不能即時更新

    一旦 JWT 簽名,它不能被撤銷或更新,它將被認為是可行的,至簽名有效和未過期。

    如果用戶的訪問權限改變(通常是降低),用戶仍將擁有刪除訪問資源的權限,直至 JWT 過期。類似地,如果 JWT 包含基於角色的授權信息,新的授權範圍直到舊 JWT 到期才會生效。換句話說,JWT 不適合即時撤銷,用戶可以設置合適的過期時間來緩解這個問題。

  • 多設備和撤銷難題

    在 JWT 到期前不可能驗證所有發行的 JWT 來實施所有設備用戶的撤銷行動。雖然理論上可以撤銷簽名密鑰使 JWT 無效,但這也將使使用該密鑰的所有 JWT 無效,此外處理緩存密鑰的過程使得此方法對於簡單用戶撤銷行動來說不切實際。

某些身份供應商可能已為這些 JWT 問題提供預構解決方案。欲了解更多信息,請參閱「改善 JWT 驗證體驗的最佳實踐。

JWT 和 Session 有什麼區別?

會話和 JWT 是在無狀態 HTTP 世界中持續驗證和授權上下文的兩種流行方法。這兩種方法都有其優勢和缺點,提供不同的優缺點。

會話,對個別請求的授權提供更強的保障,並且更容易安全地實施。然而,它們對伺服器端數據庫驗證的依賴引入了延遲開銷,這可能會對用戶體驗造成負面影響,特別是在高響應性應用程式中。

另一方面,JWT 更具快速授權和與外部應用程式互通的優勢,但需要更多開發者來處理安全複雜性。例如,我們可以使用 webhooks 通知客戶端用戶的訪問權限被撤銷,從而使客戶端清除已緩存的 JWT,並強制用戶重新驗證。

由於基於令牌的驗證對於擴展來說更合適,其劣勢仍然可控,它正在被越來越多的現代應用程序採用。

Session vs. JWT: 選擇合適的方法

你的驗證方法應該匹配你的應用程式結構和具體需求。以下是一個快速指南來幫助你決定:

何時使用基於會話的驗證

基於會話的驗證最適合在你需要即時會話控制、集中管理或擴展性不是主要問題時使用。在以下情況中尤其適用:

  • 具有持久會話的 Web 應用程式

    對於像在線購物網站這樣的平台,會話是用於跟蹤用戶、購物車和偏好的關鍵。

  • 需要即時會控製的應用

    像銀行或金融服務這樣的應用程式受益於由伺服器控制的會話數據,確保了健壯的訪問管理和安全性。

  • 單伺服器或小規模系統

    內部工具或沒有嚴重擴展需求的小型應用程序受益於簡單的會話管理,便於操作和可靠性。

何時使用 JWT 驗證

JWT 驗證更適合優先注重可擴展性、效率和分佈式系統的應用。它對於客戶端和伺服器之間的無狀態互動尤其有用。考慮以下情況時,使用基於令牌的驗證:

  • 單點登入(SSO)

    JWT 非常適合單點登入,允許用戶進行一次身份驗證,並使用相同的令牌無縫訪問多個服務或應用。與使用 JWT 格式的訪問令牌ID 令牌基於雲的應用的探索中,與OAuth 2.0 和 OIDC分享詳細說明。

  • 移動應用程式

    移動應用不遺部分偏好使用 JWT 進行驗證,因為可以安全地將令牌儲存在設備上,並以每個 API 請求發送。探索JWT驗證的快速整合Android / iOS

  • 微服務架構

    在微服務環境中,JWT 允許每個服務獨立驗證令牌,而不用依賴於集中式會話存儲,這可確保可擴展性和效率。

  • 跨域驗證

    JWT 在涉及多個域或子域的情境中表現優異(例如,api.example.comdashboard.example.com,和 docs.example.com)。與 cookies 不同,JWT 允許域間的身份驗證而無需額外的依賴關係。

  • API 和 Web 服務

    RESTful API和 Web 服務通常使用 JWT 進行驗證,因為它們輕便,可攜帶,且消除了伺服器端會話管理的需求。了解更多關於機器間驗證的項目,在這些情境中當你的應用需要直接與資源進行通訊。

改善 JWT 驗證體驗的最佳實踐

JWT 驗證是一個很棒的工具,但它會帶來影響用戶體驗的挑戰。Logto提供了一種簡便且可靠的解決方案來克服這些困難,使它成為安全且高效的驗證的最佳選擇。

處理 JWT 的用戶登出問題

一個與 JWT 驗證相關的常見問題是確保用戶具有合適的登出體驗。Logto 使用其開箱即用的 SDK 簡化了這個過程。

  • 通過在客戶端清除令牌和本地會話,並將用戶重定向到 Logto 的結束會話端點,你可以輕鬆終止客戶端應用程式和伺服器上的會話。
  • 此外,Logto 支持後通道登出,允許 AuthServer 在用戶登出時通知所有共享相同會話的客戶端應用程式。

這確保了你系統的會話管理始終一致且安全。了解更多關於登出機制以及如何實施登出

處理用戶許可變更

管理 JWT 實施中用戶許可的即時變更也可能很難。由於 JWT 本質上是無狀態的,任何更新的許可或角色直到令牌過期才會生效。Logto 提供了有效的策略來解決這個問題:

  • 降低此用戶的許可: 使用簡短的訪問令牌過期時間或通過 API 調用動態驗證權限。
  • 為此用戶新增的許可: 更新 AuthServer 以包含新的許可範圍,並重新徵得用戶的同意以套用這些變更。

這些解決方案有助於保持許可的更新以及確保更安全和響應的系統。了解更多關於即時處理用戶許可變更

Logto,作為一個可擴展的身份訪問管理基礎設施,提供完整的身份解決方案,並提供雲端服務開源版本