JWT 權杖詳解:結構、安全性與最佳實踐
JSON Web Token 幾乎出現在每個現代身份驗證系統中。你 Authorization 標頭中那串長長的字串——eyJhbGciOiJIUzI1NiIs...——就是一個 JWT,理解它的內部構造和運作原理對於建構安全的應用程式至關重要。
什麼是 JWT?
JWT 是一種精簡、URL 安全的權杖格式,用於在兩個實體之間傳遞聲明(claims,即資料)。它是自包含的——權杖本身就攜帶了驗證其真實性和提取使用者資訊所需的一切資訊,無需查詢資料庫。
使用我們的 JWT 編碼器/解碼器 即時解碼任何 JWT。貼上權杖即可看到其標頭、負載和簽名的詳細拆解。
JWT 結構:三個部分
每個 JWT 都有三個以點號分隔的 Base64URL 編碼部分:
header.payload.signature
標頭(Header)
{
"alg": "HS256",
"typ": "JWT"
}
指定簽名演算法和權杖類型。
負載(Payload)
{
"sub": "user123",
"name": "Alex Chen",
"role": "admin",
"iat": 1708963200,
"exp": 1709049600
}
包含聲明(claims)——實際的資料。標準聲明包括 sub(主體)、iat(簽發時間)和 exp(過期時間)。
簽名(Signature)
透過使用密鑰對編碼後的標頭和負載進行簽名而建立。這可以防止篡改——任何修改都會使簽名失效。
JWT 身份驗證的運作方式
- 使用者以憑證登入
- 伺服器建立包含使用者聲明的 JWT 並簽名
- 伺服器將 JWT 回傳給客戶端
- 客戶端在後續請求的 Authorization 標頭中攜帶 JWT
- 伺服器驗證簽名並提取聲明——無需查詢資料庫
安全最佳實踐
務必驗證簽名
絕不要信任未經簽名驗證的 JWT。在開發階段可以使用我們的 JWT 解碼器 來檢查權杖,但在生產環境中必須始終進行密碼學驗證。
使用較短的過期時間
JWT 一旦簽發就無法撤銷(不像 Session 權杖)。將過期時間設為較短(15-60 分鐘),並使用 Refresh Token 來維持長期工作階段。
選擇正確的演算法
- HS256 — 使用 SHA-256 的 HMAC,對稱金鑰。簡單、快速,適合單一伺服器應用
- RS256 — 使用 SHA-256 的 RSA,非對稱金鑰。更適合多個服務需要驗證權杖的分散式系統
- 絕對不要使用 "none" —
alg: "none"漏洞已經在現實世界中造成過資料外洩
保護密鑰
你的 JWT 簽名金鑰是身份驗證系統的主鑰匙。安全地儲存它、定期輪換,並且絕不要在客戶端程式碼中暴露。
不要在負載中存放敏感資料
JWT 負載是 Base64 編碼的,不是加密的。任何人都可以解碼。絕不要放入密碼、信用卡號碼或機密資訊。
常見的 JWT 錯誤
- 未驗證過期時間 — 務必檢查
exp聲明 - 將 JWT 存放在 localStorage — 容易受到 XSS 攻擊。改用 httpOnly Cookie
- 權杖過大 — JWT 會包含在每個請求標頭中。保持負載精簡
- 未使用 HTTPS — 透過 HTTP 發送的 JWT 可能被攔截
常見問題
可以撤銷 JWT 嗎?
不能直接撤銷——JWT 是無狀態的。替代方案包括設定較短的過期時間、建立權杖黑名單,或更換簽名金鑰(這會使所有權杖失效)。
應該使用 JWT 來管理工作階段嗎?
JWT 非常適合 API 身份驗證和微服務架構。對於傳統的 Web 工作階段,使用 Cookie 的伺服器端 Session 通常更簡單也更安全。
JWT 和 OAuth 有什麼區別?
OAuth 是一個授權框架。JWT 是一種權杖格式。OAuth 可以使用 JWT 作為存取權杖,但它們解決的是不同的問題。
相關資源
- Base64 編碼詳解 — 了解 JWT 使用的編碼方式
- 理解 JWT 安全性 — 深入探討漏洞
- JWT 編碼器/解碼器 — 即時解碼和建立 JWT
- 雜湊產生器 — 探索 JWT 簽名背後的演算法