JWT 與 Session 驗證比較
學習基於 Session 和 JWT 驗證的差異。探索權衡、優勢和使用案例,以為你的應用選擇合適的驗證方案。
一般來說,使用應用程式的第一步是驗證,用戶需提供身份憑證以成功登錄。完成這步驟後,身份系統(即身份提供者、驗證伺服器等)即知曉用戶身份以及其能訪問的資源。
鑑於 HTTP 本質上無狀態,Session 中的每個請求都是獨立的,無法回憶先前的資訊。每次動作都要重新驗證用戶相當麻煩,並會損害用戶體驗。
讓我們來看看 基於 Session 的驗證 與 JWT (JSON Web Tokens) 驗證,這兩種維護驗證狀態的熱門方法。每種方法都有其獨特的優勢和權衡,而選擇取決於你的應用程式的具體需求。如果你正在這兩者之間做決定,本指南將為你提供幫助。
什麼是基於 Session 的驗證?
基於 Session 的驗證依賴於伺服器來維護用戶的驗證狀態記錄。通過創建和管理 Session,伺服器可以讓用戶保持登錄狀態,並繼續與應用程式互動,而無需每次請求都重新輸入憑證。
基於 Session 的驗證如何運作?
Session 創建
- 用戶驗證並提供一些憑證(如電子郵件和密碼)。
- 如果憑證有效,伺服器會創建一個代表該Session的持久記錄。該 Session 包含多種資訊,如隨機字符串、用戶標識、Session 開始時間、Session 到期時間等 。
SessionID
會儲存在數據庫中並作為Cookie回傳到用戶的客戶端。
Session 驗證
- 該過程可以由用戶手動觸發(例如,點擊標籤,刷新頁面)或由客戶端自動觸發(例如,在初始頁面載入或透過 API 調用
SessionID
)。 - 每次後續調用都會從客戶端發送包含 Session Cookie 的 HTTP 請求到伺服器。
- 伺服器通過查詢存儲於伺服器的 Session 數據來驗證
SessionID
。 - 如果有效,伺服器處理請求並授權用戶。
如何撤銷 Session?
可以即時使 Session 失效,這對於需要快速撤銷訪問的情況非常有用。
- 用戶手動登出:伺服器刪除 Session 記錄,也就是有效地將用戶登出。
- 管理員強制用戶登出:管理員或系統可透過刪除資料庫中的特定 Session 來終止它。例如,在發生安全漏洞時。
- Session 到期:Session 可以在非活躍一段時間後自動到期,或設置固定期限。
基於 Session 的驗證的優點
- 簡單可靠:Session 記錄提供了一個明確、集中化的信息來源,從而更高信任度,並且讓授權決策更可靠。
- 即時撤銷:通過刪除或使 Session 記錄失效,可迅速撤銷用戶的訪問權限。
基於 Session 的驗證的缺點
- 分佈式系統中的延遲:在多個伺服器之間保持同步 Session 數據需要同步 Session 儲存。這會引入額外的延遲,因為伺服器每次請求都必須檢查 Session 儲存。
- 高資源消耗:每個 Session 都佔用伺服器資源,當用戶規模擴大時會影響性能。
- 安全風險:Session 劫持(透過被竊取的 Session Cookie)可能讓未授權的人士訪問用戶帳戶。
- 對 API 的有限使用:基於 Session 的驗證對於行動應用程式來說並不是很理想。因為它在伺服器上儲存 Session 數據,當用戶數量多時會增加負擔和複雜性。此外,它使用 cookies,在行動設備上較難管理。
什麼是 JWT 驗證?
JSON Web Tokens (JWTs) 採用不同的方法,將所有相關的用戶信息直接嵌入到一個 JSON 對象的 Token 中。與基於 Session 的方法不同,JWTs 是無狀態的,意味著伺服器不管理驗證記錄。
JWT 驗證如何運作?
JWT 包含三部分:標頭、有效載荷和簽名。
- 標頭包含簽名算法(如 HS256)和 Token 的類型(JWT)。
- 有效載荷包含核心聲明,例如用戶身份、用戶角色和到期時間。
- 簽名使用密鑰對標頭和有效載荷進行簽名,允許驗證簽名是否被篡改。
JWT 發行
- 用戶端將用戶憑證發送至驗證伺服器(對於跨域管理訪問,通用身份提供者特別有益)。
- 驗證成功後,伺服器生成包含標頭、有效載荷和簽名的 JWT。
- AuthServer 將發行的 Token 發送給客戶端。客戶端儲存 JWT(例如,在 cookies、localStorage 或 sessionStorage)。
基於 Session 的工作流程遵循類似的過程。然而,驗證後,用戶信息儲存在伺服器內的 Session 中,而 JWT 依賴於 Token 發送至客戶端進行儲存和後續使用。
Token 驗證
- 對於後續的 API 請求,客戶端將 JWT 發送在
Authorization
標頭中(Bearer <token>
)。 - 伺服器使用密鑰或公鑰驗證 JWT 的簽名並檢查其聲明(例如過期、發行者)。
- 如果 Token 有效,伺服器授權客戶端訪問請求的資源。
基於 Session 的驗證需要伺服器查詢一個 Session 儲存器,這在依賴外部或集中式數據庫時可能會很慢。 相比之下,JWT 驗證是無狀態的,所有必要的信息儲存在客戶端的 Token 中,並使用簽名來確保安全性。這消除了 Session 管理的需要,尤其是在分佈式系統中,使其更快速和可擴展。
如何撤銷 JWT?
在客戶端,簽出通常意味著清除本地 Session 並從儲存中移除 Token(ID、訪問、刷新 Token)。然而,對於 JWT 驗證,這僅在本地簽出用戶,與授權伺服器的集中 Session 保持不變。因此,除非 Token 到期或手動終止,用戶可能仍能訪問同一 Session 下的其他應用程式。
撤銷 JWT (JSON 網路 Token)比基於 Session 的驗證更具挑戰性,因為 JWT 是無狀態的,除非實施特定策略,否則一旦發行就無法使其失效。常見的方法包括:
- 短效期:設置一個短的
exp
聲明(例如,15 分鐘)給 JWT。一旦過期,用戶必須重新驗證。這將 Token 被洩露的風險降至最低,因為攻擊者只能在有限時間內使用它。為了保持流暢的用戶體驗,刷新 Token 可以用來將重新驗證的影響降到最低。 - Token 黑名單:對於關鍵情況(例如,用戶登出、密碼更改),保持一個撤銷 Token 的黑名單。伺服器檢查出來的 Token 是否在這個黑名單中,並拒絕任何匹配項。雖然有效,但這種方法需要跟蹤撤銷的 Token,這有悖於 JWT 的無狀態特性,名單增長過大可能會變得低效。
- 撤銷端點:在授權伺服器上引入一個撤銷端點以便使 Token(例如,刷新 Token)失效。 一旦刷新 Token 被撤銷,任何從它發行的訪問 Token 將不再被續期。這種方法在 OAuth2 流程中非常有效。
JWT 驗證的優點
- 快速且更具資訊性:JWT 的自包含特性使得客戶端驗證更快速高效,無需與伺服器交互。 它們還可包括自定義聲明(例如,用戶角色或其他相關數據)在 Token 中,從而使伺服器能在不查詢數據庫的情況下確定角色。
- 增強安全性:JWT 使用簽署和加密技術,使得攻擊更困難。
- 跨域支持:JWT 非常適用於單點登入(SSO)和跨域驗證。 它們允許用戶以同一 Token 在多個域或服務中進行驗證。
- 行動友好:JWT 對需要無狀態驗證的行動應用程式來說非常有效。Token 可以儲存在客戶端,並隨每次請求提供,提升效率和使用便利。
JWT 驗證的缺點
-
JWT 不會實時更新
一旦 JWT 被簽署,無法撤銷或更新,只要簽名有效且未過期,就會被認作有效。
如果用戶的訪問權限改變(通常降低),用戶將繼續對資源有已移除的訪問權限,直到 JWT 到期。 同樣,如果 JWT 包含基於角色的授權信息,新的授權範圍將不會在舊 JWT 到期之前生效。 換句話說,JWT 不適用於實時撤銷,用戶可以設置適當的到期時間來緩解該問題。
-
多設備和撤銷困境
不可能在所有發行的 JWT 到期之前進行驗證以實現所有設備的用戶撤銷。 雖然理論上可以撤銷簽署密鑰來使 JWT 失效,但這也會使所有使用該密鑰的 JWT 失效,處理快取密鑰的過程讓這種方法對於簡單的用戶撤銷操作來說不切實際。
某些身份提供者可能已針對這些 JWT 問題提供現成的解決方案。想要了解更多信息,請查看 "增強 JWT 驗證體驗的最佳實踐。”
JWT 與 Session 的區別是什麼?
Session 和 JWT 是二種在無狀態 HTTP 世界中持續驗證和授權上下文的流行方法。 雖然這兩種方法都有其利弊,但它們提供了不同的好處和缺點。
Session 為每個請求的授權提供了更強的保證,可以更簡單地安全實施。但它們依賴於伺服器端數據庫驗證,這引入の的延遲,可能對高響應應用程式的用戶體驗造成負面影響。
另一方面,JWT 因更快的授權和與外部應用程式的互操作性而有利,但需要更多開發者的努力來解決安全性的複雜性。 例如,我們可以使用 webhooks 通知客戶端用戶的訪問被撤銷,這樣客戶端可以清除快取的 JWT 並迫使用戶重新驗證。
由於基於 Token 的驗證更適合擴展,其缺點仍可被管理,越來越多的現代應用程式正在採用它。
Session 與 JWT:選擇正確的方法
你的驗證方法應與應用程式的架構和具體需求相匹配。以下是一個快速指南幫助你做決定:
何時使用基於 Session 的驗證
當你需要實時的 Session 控制,需集中管理或擴展性不是主要考慮時,基於 Session 的驗 證效果最好。以下是它發揮突出作用的情況:
-
具有持續 Session 的 Web 應用程式
對於如網上購物網站這樣的平台,Session 對於跟踪用戶、購物車和偏好配置是必要的。
-
需要實時 Session 控制的應用程式
如銀行或金融服務等應用程式受益於伺服器控制的 Session 數據,保證強健的訪問管理和安全性。
-
單伺服器或小型系統
不需要大量擴展的內部工具或小型應用程式依靠簡單的 Session 管理以便於使用和可靠性。
何時使用 JWT 驗證
JWT 教認更適合優先考慮擴展性、效率和分佈式系統的應用程式。 它特別適用於客戶端和伺服器間的無狀態交互。考慮以下場景使用基於 Token 的驗證:
-
單點登入 (SSO)
JWT 非常適用於單點登入,允許用戶一次驗證即能無縫訪問多個服務或應用,都是使用同一 Token。詳細解釋使用 OAuth 2.0 和 OIDC 保護雲端應用,在 訪問 Token 和 ID Token 上皆使用 JWT 格式。
-
行動應用程式
行動應用程式一般更偏好使用 JWT 驗證,因為 Token 可以安全地儲存在設備上,並隨著每次 API 請求發送。探索Android / iOS 中快速整合 JWT 驗證。
-
微服務架構
在微服務環境中,JWT 允許每個服務獨立驗證 Token 而不依賴中心 Session 儲存,保證擴展性和效率。
-
跨域驗證
JWT 在涉及多個域或子域的場景中表現出色(例如,
api.example.com
,dashboard.example.com
,和docs.example.com
)。 與 cookies 不同,JWT 允許跨域驗證而無需額外依賴。 -
API 和 Web 服務
RESTful APIs 和 Web 服務通常使用 JWT 進行驗證,因為它們輕量、便攜,並消除伺服器端 Session 管理的必要性。了解更多機器對機器驗證場景,讓你的應用能夠直接與資源通信。
改善 JWT 驗證體驗的最佳實踐
JWT 驗證是一個強大的工具,但它可能帶來影響用戶體驗的挑戰。Logto 提供了一個簡單和可靠的解決方案來克服這些困難,使其成為安全且高效的驗證的首選。
處理 JWT 的用戶登出問題
JWT 驗證的一個常見問題是確保正確的用戶登出體驗。 Logto 透過其現成的 SDK 簡化了這一過程。
- 通過清除客戶端上的 Token 和本地 Session,並將用戶重定向到 Logto 的 結束 Session 端點,你可以輕鬆終止客戶端應用程式與伺服器上的 Session。
- 此外,Logto 支持 後通道登出,使 AuthServer 能在用戶登出時通知所有使用相同 Session 的客戶端應用程式。
這確保了你生態系統中的一致和安全的 Session 管理。 了解更多關於登出機制和如何實施登出。
處理用戶權限變更
使用 JWT 管理用戶權限的實時變更也可能較為棘手。由於 JWT 本質上是無狀態的,任何更新的權限或角色可能不會生效,直到 Token 到期。 Logto 提供策略來有效處理此問題:
- 對於降低該用戶的權限: 使用短的訪問 Token 到期時間或透過 API 調用動態驗證權限。
- 對於為該用戶增加新權限: 更新 AuthServer 以包含新的權限範圍,並重新同意用戶以應用這些變更。
這些解決方案有助於保持權限更新,確保更安全、更快速的系統。了解更多關於管理用戶權限的實時變更。