跳至主要内容

Json Web Token

JSON Web Token (JWT) 定義在 RFC 7519,用於實現雙方之間的安全通信。

考慮到一個可以用來表示用戶的 JSON 物件:

{
"sub": "subject",
"name": "username"
}

並且,可以使用數字簽名的機制,來確保該數據在傳輸過程中沒有被竄改過:服務器使用其私鑰簽署這個 JSON 物件,然後客戶端可以使用服務器的公鑰驗證這個簽名。

內容格式

JWT 包含了以下內容:

  1. header - 算法和類型
  2. payload - 實際數據
  3. signature - 涵蓋頭部和載荷的簽名

並使用 {{header}}.{{payload}}.{{signature}} 的形式連接起來。考慮到一些字符對於網路傳輸不友好,因此 Header 與 Payload 會先使用 base64 編碼

jwt

{
"alg": "HS256",
"typ": "JWT"
}

base64編碼後輸出 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022
}

base64編碼後輸出 eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0

最後使用 HMAC(base64Url(header) + "." + base64Url(payload), secret) 輸出 signature,最終輸出以下內容為 JWT

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30

簽名算法

在前面算法我們使用了 HMAC,來進行計算簽章的計算,這是一種對稱加密演算法。簽署(Sign)Token 和驗證(Verify)Token 使用的是 同一把私鑰(Private Key)。

另外一種作法是基於非對稱加密演算法,IdP 保存私鑰,用來簽署 Token;同時將公鑰給公開,允許任何人下載後驗證 Token 的真實性質。

特性HSRS、ES、PS 系列
類型對稱式 (Symmetric)非對稱式 (Asymmetric)
金鑰數量1 把2 把 (Private & Public Key)
安全性較低(私鑰分發困難)較高(僅簽署方需私鑰)
速度較慢
適用場景單一應用程式、內部服務微服務架構、第三方授權 (OAuth2)

在現代的開發中,我推薦使用橢圓曲線數字簽名算法 (ECDSA) ,能夠建立更緊湊的簽名,且性能更加高效率。

驗證方式

  1. 使用 . 分隔 JWT 的三個部份
  2. 使用 base64 解碼 Header 與 Payload
  3. 根據 Header 登記的算法,與應用持有的金鑰對簽章進行驗證