JWT(JSON Web Token)是一種用於在各方之間安全傳輸資訊的基於JSON格式的令牌,通常用於身份驗證和授權。JWT令牌的結構相對簡單,易於傳遞,並且可以在任何網路通訊協議中(如HTTP)使用。以下是對JWT的詳細解釋以及它的工作過程。
一、JWT 的結構
JWT 由三部分組成,每部分使用點號 (.
) 分隔:
- Header(頭部)
- Payload(載荷)
- Signature(簽名)
例如:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
1. Header(頭部)
頭部通常由兩部分資訊組成:
- 宣告型別:即令牌的型別,JWT。
- 加密演算法:例如HMAC、SHA256、RSA等。
{
"alg": "HS256",
"typ": "JWT"
}
上面的頭部使用了 HS256
(HMAC-SHA256)作為簽名演算法,並且宣告這是一個JWT令牌。頭部會被編碼為Base64Url格式。
2. Payload(載荷)
Payload 是JWT的主體部分,包含需要傳遞的資料。這些資料稱為宣告(claims)。JWT宣告有三類:
- 註冊宣告(Registered claims):如
iss
(釋出者)、exp
(過期時間)、sub
(主題)、aud
(受眾)。 - 公共宣告(Public claims):由雙方自行定義,常用於身份驗證,比如使用者名稱、使用者ID等。
- 私有宣告(Private claims):僅用於雙方之間的資訊交換,例如特定應用上下文下的自定義資訊。
一個常見的Payload示例:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022
}
Payload同樣被編碼為Base64Url。
3. Signature(簽名)
簽名部分用於驗證訊息的真實性,防止資料在傳輸過程中被篡改。簽名的生成過程如下:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret_key
)
簽名部分確保令牌在傳輸中不會被偽造或篡改。
二、JWT 的工作流程
JWT的工作過程可以分為建立和驗證兩部分,以下是詳細的工作步驟:
1. 使用者登入並請求令牌
使用者透過提交有效的憑據(如使用者名稱和密碼)向伺服器發出登入請求。伺服器驗證這些憑據。
2. 伺服器生成 JWT
如果使用者的憑據正確,伺服器會生成一個JWT令牌。令牌中通常會包含以下資訊:
- 使用者的身份資訊(如使用者ID)。
- 有效期(expiration time)。
- 其他相關資訊(如使用者角色等)。
伺服器會透過頭部、載荷和簽名來構造JWT。建立後的JWT如下所示:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
生成後的JWT透過HTTP響應返回給使用者(通常是在HTTP header中返回,或在響應體中返回)。
3. 使用者請求受保護的資源
使用者在後續的每次請求中,會將JWT放在請求頭中,比如在Authorization
頭中使用Bearer方案:
Authorization: Bearer <JWT Token>
4. 伺服器驗證 JWT
每次使用者請求受保護資源時,伺服器會收到JWT,並進行以下驗證:
-
完整性檢查:伺服器透過重新計算簽名並與收到的JWT的簽名進行比較,確保JWT沒有被篡改。它會使用伺服器端的金鑰來驗證。
-
過期檢查:伺服器檢查JWT的
exp
(過期時間)欄位,確保令牌未過期。如果令牌過期,伺服器將拒絕請求並要求使用者重新認證。 -
許可權驗證:伺服器檢查JWT中的宣告是否包含使用者有權訪問的資源。如果使用者的許可權不足,伺服器會拒絕請求。
5. 成功訪問受保護資源
如果JWT透過了所有的驗證,伺服器會允許使用者訪問受保護的資源,並返回所需的響應。
三、JWT 的優勢
-
無狀態性:JWT 是無狀態的,伺服器無需在本地儲存會話資料,這減少了伺服器的儲存負擔。
-
可擴充套件性:因為JWT是在客戶端儲存的,令牌中可以攜帶與使用者相關的額外資訊,如角色、許可權等,便於進行身份驗證和授權。
-
跨域認證:JWT 可以輕鬆用於跨域認證,因為它是以JSON格式的令牌,可以在多個不同的服務之間共享。
-
簡潔和易傳輸:JWT令牌結構簡單,且透過Base64編碼,適合用於HTTP頭中傳遞。並且令牌體積小,減少頻寬佔用。
四、JWT 的缺點
-
不可撤銷性:由於JWT是無狀態的,伺服器生成後無法撤銷已經發出的令牌。通常解決辦法是透過設定較短的過期時間,並配合重新整理令牌機制。
-
資訊公開:JWT的Payload部分是Base64編碼的,不是加密的。雖然第三方無法偽造令牌,但他們可以解碼並檢視載荷中的資訊。因此,在JWT中不要包含敏感資訊。
-
令牌過期問題:如果JWT沒有及時過期,或沒有撤銷機制,那麼一旦令牌洩露,攻擊者可以一直使用這個令牌進行惡意操作。
五、典型的JWT使用場景
-
使用者身份驗證:最常見的場景是在單點登入(SSO)系統中,JWT 用於在多個系統之間共享使用者身份驗證狀態。
-
OAuth 授權:OAuth 2.0 中,JWT 被用作訪問令牌來授權使用者訪問API資源。
-
微服務架構:在微服務架構中,JWT 可以在不同的微服務之間傳遞使用者身份資訊,避免每個微服務都需要獨立進行身份驗證。
六、JWT 與其他認證方法的對比
-
基於會話的認證:傳統的基於會話的認證通常需要在伺服器端儲存使用者的會話資訊,而JWT是無狀態的,無需在伺服器上儲存使用者狀態。
-
OAuth:JWT 常用於OAuth中作為訪問令牌,與OAuth的授權流程緊密結合。相比OAuth的複雜性,JWT本身更簡潔。
七、總結
JWT(JSON Web Token)是一種基於JSON的輕量級令牌,用於在客戶端和伺服器之間安全傳遞資訊。透過它的三部分結構(頭部、載荷和簽名),JWT確保資料的完整性和安全性。在現代Web開發中,JWT廣泛用於身份驗證和授權,特別是在微服務和跨域應用場景中。