一、引言:為什么“無狀態”如此迷人
HTTP 協議天生無記憶,每一次請求都是一次“陌生人對話”。Cookie、Session、Token 輪番登場,只為解決一句靈魂拷問:“這個請求者到底是誰?”
JWT(JSON Web Token)用三段 Base64 字符串,把身份信息、權限范圍、過期時間封裝成自包含的“數字契約”,讓服務器擺脫 Session 存儲枷鎖,也讓微服務間傳遞信任變得像快遞包裹一樣簡單。
本文嘗試用近四千字,把 JWT 的生成、驗證、攻防、演進、落地故事串成一本可隨身攜帶的“令牌手冊”。
二、歷史脈絡:從 Session Cookie 到 Stateless Token
- 1994:Netscape 推出 Cookie,服務端用 Set-Cookie 種下 SessionID,瀏覽器每次自動回傳。
- 2000 年代:Session 存儲在內存、Redis、數據庫,橫向擴展時帶來“粘性會話”噩夢。
- 2010:OAuth 2.0 普及,Token 成為授權主流,JWT 作為其輕量級表示被納入 RFC 7519。
- 2020:微服務、Serverless、邊緣計算興起,無狀態成為架構剛需,JWT 成為“最小信任單元”。
三、令牌解剖:三段字符串的密碼學契約
JWT 由 Header、Payload、Signature 三段組成,用兩個點號連接,形如 `aaaa.bbbb.cccc`。
1. Header
聲明類型(JWT)與簽名算法(HS256、RS256、ES256…)。
2. Payload
承載業務數據(sub、iat、exp、scope…),官方定義 7 個標準字段,也可自定義私有字段。
3. Signature
用 Header 指定的算法對 “Base64(Header) + . + Base64(Payload)” 進行簽名,確保篡改即失效。
三段字符串既可放在 HTTP Header、URL 查詢參數,也能塞進 Cookie,甚至 QR 碼。
四、生成流程:從用戶登錄到頒發令牌
1. 認證
用戶提交憑證,服務端驗證賬號密碼、短信驗證碼或生物特征。
2. 授權
查詢角色權限,組裝 Payload:用戶 ID、角色列表、過期時間、發行者。
3. 簽名
根據安全級別選擇對稱(HMAC)或非對稱(RSA/ECDSA)算法生成簽名。
4. 頒發
通過 HTTP 200 響應返回 JWT,客戶端存于內存、Cookie、LocalStorage 或移動端 Keychain。
5. 刷新
搭配 Refresh Token 機制,讓長周期權限無需重輸密碼。
五、驗證流程:從令牌到身份確認的“三步曲”
1. 格式校驗
檢查三段結構、Base64 完整性、JSON 可解析性。
2. 簽名驗證
用 Header 中聲明的算法與密鑰重新計算簽名,比對一致性。
3. 業務校驗
檢查 exp(過期)、nbf(生效)、iss(發行者)、scope(權限范圍)是否滿足當前請求。
任何一步失敗即返回 401 Unauthorized,并附帶 WWW-Authenticate 頭部提示原因。
六、簽名算法:對稱與非對稱的權衡
- HMAC(HS256/HS512)
計算快、密鑰短,適合內部微服務;缺點是共享密鑰泄露即全線失守。
- RSA(RS256)
私鑰簽名、公鑰驗證,密鑰分離,適合跨域、開放平臺;計算量略大。
- ECDSA(ES256)
同等安全強度下密鑰更短、簽名更小,移動端友好,但實現復雜。
選擇原則:性能敏感選 HMAC,開放平臺選 RSA/ECDSA,必要時混合使用(JWT + JWE 加密 Payload)。
七、攻防實錄:六類常見攻擊與防御
1. 簽名偽造
攻擊者把 alg 改為 none,刪除簽名。防御:強制驗證 alg 白名單。
2. 密鑰泄露
對稱密鑰被拖庫。防御:密鑰輪換、環境變量注入、使用非對稱方案。
3. 重放攻擊
被盜令牌再次使用。防御:exp 短周期 + Refresh Token,或綁定 IP、UA、指紋。
4. 算法混淆
把 RS256 公鑰當成 HMAC 密鑰。防御:解析 Header 后拒絕非預期算法。
5. 敏感信息泄露
Payload 明文暴露用戶郵箱、手機號。防御:使用 JWE 加密或最小字段原則。
6. 令牌劫持
XSS 竊取 LocalStorage 中的 JWT。防御:HttpOnly Cookie + SameSite + CSP。
八、生命周期管理:短令牌與長會話
- 有效期策略
訪問令牌 15 min、刷新令牌 7 天,既降低泄露窗口,又避免頻繁登錄。
- 撤銷機制
由于 JWT 無狀態,服務端需維護“黑名單”或使用版本號(jti)+ 分布式緩存。
- 滑動窗口
每次請求后刷新 exp,實現“活躍續命”。注意并發場景下的競態條件。
九、進階場景:微服務、網關、邊緣計算
1. 網關統一鑒權
邊緣網關驗證簽名后,把解析后的用戶 ID 注入請求頭,下游服務無需二次解析。
2. 微服務間調用
內部服務使用 HMAC 短令牌,跨域服務使用 RSA 長令牌,實現“內外有別”。
3. 邊緣函數
在 CDN Worker 中驗證 JWT,拒絕非法請求,減少回源流量。
4. 多租戶
iss 字段區分租戶,scope 字段區分權限,實現“一張令牌,多域通行”。
十、工具與生態:調試、可視化、測試
- 在線解碼器:粘貼令牌即可查看 Header、Payload、簽名驗證結果。
- 單元測試:用固定密鑰與已知負載生成“金樣本”,斷言解析結果。
- 安全掃描:集成 OWASP JWT Cheat Sheet,自動檢測弱算法、缺失字段。
- 監控告警:令牌過期前 5 min 觸發通知,防止用戶體驗斷崖。
十一、未來展望:JWT 2.0 與去中心化身份
- JOSE 擴展:支持 EdDSA、BLS12-381 后量子算法。
- Verifiable Credentials:把 JWT 作為可驗證憑證的一部分,實現去中心化身份(DID)。
- 零知識證明:在不暴露隱私字段的情況下證明“我已成年”。
當 Web3 來臨時,JWT 或許不再是“服務端頒發”,而是“用戶自證”。
十二、每日一練:親手簽發與驗證
1. 準備:選擇一種簽名算法,生成密鑰對。
2. 構造:編寫 Header 與 Payload,填入標準字段與自定義聲明。
3. 簽名:使用工具或庫生成 Signature。
4. 驗證:把令牌放到解碼器中,觀察篡改后的錯誤提示。
5. 思考:如果把 exp 改成 1970,會發生什么?
十三、結語:令牌即契約
JWT 的簡潔讓它易于傳播,也容易被誤用。
真正的安全不在于算法多高級,而在于:
- 最小披露:只把必要信息放進 Payload;
- 最小信任:密鑰、算法、有效期隨時可輪換;
- 最大驗證:每一次請求都重新校驗簽名與業務規則。
當下一次你拿到一串三段點號分隔的字符,請記得:
它不僅是一張通行證,更是一份數字時代的信任契約。