JSON Web Tokens (JWT) 詳解:結構、簽名與安全實踐
在開發網站、應用程序或API時,用戶登錄和身份驗證是不可避免的需求。JSON Web令牌(JWT)正是解決這一問題的常用方案,它能在不同系統間安全地傳遞身份驗證憑證。
本文將深入講解:
- JWT的基本概念
- JWT的結構與生成原理
- 不同的JWT簽名技術與算法(對稱與非對稱)
- JWT在實際身份驗證流程中的應用
- 使用JWT的安全最佳實踐
JWT是什么?
JSON Web令牌(JWT)是一種開放標準(RFC 7519),它定義了一種緊湊且自包含的方式,用于在各方之間作為JSON對象安全地傳輸信息。由于采用數字簽名,這些信息可以被驗證和信任。JWT可以使用密鑰(HMAC算法)或RSA/ECDSA的公私鑰對進行簽名。 —— jwt.io對JWT的介紹
簡單來說,JWT就像一封帶有防篡改封印的信件。它是一種特殊的安全消息,能在通信雙方間傳遞且確保來源可信。
每個JWT都通過以下方式之一進行數字簽名:
- 密鑰(用于HMAC等對稱算法)
- 私鑰(用于RSA/ECDSA等非對稱算法)
這些密鑰或私鑰僅由JWT簽發系統(如Auth0、AWS Cognito等身份認證服務)掌握。簽名可證明兩點:
- 真實性:確認消息確實來自聲稱的發送方
- 完整性:確保消息自簽名后未被篡改
JWT的三元結構
JWT由三個核心部分組成:
- 頭部(Header)
- 載荷(Payload)
- 簽名(Signature)
頭部
頭部包含令牌的元信息,就像包裹上的標簽說明內容物和處理方式。通常包括:
alg:指定簽名算法,如HS256或RS256typ:令牌類型,通常為JWT
示例(解碼后):
{
"alg": "RS256",
"typ": "JWT"
}載荷
這是JWT的核心數據部分,包含"聲明"(claims)信息。聲明是關于實體(通常是用戶)的陳述和附加數據??煞譃槿悾?/span>
1. 注冊聲明(推薦但不強制的標準聲明):
iss- 簽發者(如你的應用域名)sub- 主題(如用戶ID)aud- 受眾(令牌的目標接收方)exp- 過期時間(時間戳)iat- 簽發時間(時間戳)nbf- 生效時間(在此之前令牌無效)jti- 令牌唯一標識(防重放攻擊)
2. 公共聲明:可自定義的通用聲明,建議使用URI避免命名沖突
3. 私有聲明:為特定應用場景定制的聲明
示例載荷:
{
"sub":"1234567890",
"name":"張三",
"admin":true,
"iat":1678886400,
"exp":1678890000
}重要提示:載荷僅經過Base64Url編碼,而非加密!切勿在載荷中存儲密碼等敏感信息,除非整個JWT經過額外加密(JWE)。
簽名
簽名是JWT的安全核心,通過以下要素生成:
- 編碼后的頭部
- 編碼后的載荷
- 密鑰(對稱算法)或私鑰(非對稱算法)
偽代碼表示: 簽名 = 算法(Base64Url(頭部) + "." + Base64Url(載荷), 密鑰)
最終JWT格式為: Base64編碼頭部.Base64編碼載荷.Base64編碼簽名
非對稱簽名(RS256)解析
RS256算法采用RSA+SHA-256的非對稱加密體系,使用公私鑰對實現簽名驗證。
簽發流程
- 準備數據:將頭部和載荷進行Base64Url編碼并拼接
- 計算哈希:對拼接字符串進行SHA-256哈希
- 私鑰簽名:用私鑰對哈希值進行簽名
驗證流程
- 分離部件:拆分JWT為頭部、載荷和簽名
- 獲取公鑰:從JWKS端點等來源獲取對應公鑰
- 本地哈希計算:重新計算頭部+載荷的哈希值(Hash A)
- 簽名解密:用公鑰解密簽名得到原始哈希(Hash B)
- 比對驗證:Hash A與Hash B一致則驗證通過
非對稱驗證流程圖
非對稱簽名類比:鎖與鑰匙
私鑰:唯一能上鎖的特殊鑰匙,僅持有者擁有
公鑰:可驗證鎖是否由對應私鑰上鎖,但不能創建新鎖
對稱簽名:HS256(HMAC+SHA-256)
HS256采用單一共享密鑰進行簽名和驗證。
HS256工作流程
- 共享密鑰:簽發方和驗證方持有相同密鑰
- 數據組合:編碼頭部和載荷并拼接
- HMAC簽名:使用密鑰生成HMAC-SHA256簽名
- 組成JWT:拼接形成完整令牌
驗證機制
- 分離JWT部件
- 使用相同密鑰重新計算簽名
- 比對接收簽名與計算簽名
非對稱驗證流程圖
關鍵區別
- 密鑰管理:對稱算法需安全共享密鑰
- 性能:HS256計算速度通常快于RS256
實戰:典型身份驗證流程
- 用戶登錄:客戶端提交憑證到認證服務器
- 簽發JWT:服務器驗證憑證后簽發簽名令牌
- 存儲JWT:客戶端安全存儲令牌
- API調用:在請求頭中加入
Authorization: Bearer <JWT> - 驗證授權:API驗證JWT后執行請求
這種無狀態(stateless)設計簡化了服務器擴展。
JWT安全最佳實踐
- 強制使用HTTPS:防止令牌被竊取
- 保護簽名密鑰:嚴防密鑰泄露
- 短期有效令牌:設置較短過期時間(如15分鐘)
- 使用刷新令牌:維持用戶會話體驗
- 避免敏感數據:載荷內容可被解碼
- 全面驗證聲明:檢查exp、iss、aud等關鍵聲明
- 考慮撤銷機制:對于關鍵場景實現令牌黑名單




























