授權(Authorization)和認證(Authentication)

gongchengship發表於2024-10-21

JWT(JSON Web Token)是一種用於在各方之間安全傳輸資訊的基於JSON格式的令牌,通常用於身份驗證和授權。JWT令牌的結構相對簡單,易於傳遞,並且可以在任何網路通訊協議中(如HTTP)使用。以下是對JWT的詳細解釋以及它的工作過程。

一、JWT 的結構

JWT 由三部分組成,每部分使用點號 (.) 分隔:

  1. Header(頭部)
  2. Payload(載荷)
  3. 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 的優勢

  1. 無狀態性:JWT 是無狀態的,伺服器無需在本地儲存會話資料,這減少了伺服器的儲存負擔。

  2. 可擴充套件性:因為JWT是在客戶端儲存的,令牌中可以攜帶與使用者相關的額外資訊,如角色、許可權等,便於進行身份驗證和授權。

  3. 跨域認證:JWT 可以輕鬆用於跨域認證,因為它是以JSON格式的令牌,可以在多個不同的服務之間共享。

  4. 簡潔和易傳輸:JWT令牌結構簡單,且透過Base64編碼,適合用於HTTP頭中傳遞。並且令牌體積小,減少頻寬佔用。

四、JWT 的缺點

  1. 不可撤銷性:由於JWT是無狀態的,伺服器生成後無法撤銷已經發出的令牌。通常解決辦法是透過設定較短的過期時間,並配合重新整理令牌機制。

  2. 資訊公開:JWT的Payload部分是Base64編碼的,不是加密的。雖然第三方無法偽造令牌,但他們可以解碼並檢視載荷中的資訊。因此,在JWT中不要包含敏感資訊。

  3. 令牌過期問題:如果JWT沒有及時過期,或沒有撤銷機制,那麼一旦令牌洩露,攻擊者可以一直使用這個令牌進行惡意操作。

五、典型的JWT使用場景

  1. 使用者身份驗證:最常見的場景是在單點登入(SSO)系統中,JWT 用於在多個系統之間共享使用者身份驗證狀態。

  2. OAuth 授權:OAuth 2.0 中,JWT 被用作訪問令牌來授權使用者訪問API資源。

  3. 微服務架構:在微服務架構中,JWT 可以在不同的微服務之間傳遞使用者身份資訊,避免每個微服務都需要獨立進行身份驗證。

六、JWT 與其他認證方法的對比

  1. 基於會話的認證:傳統的基於會話的認證通常需要在伺服器端儲存使用者的會話資訊,而JWT是無狀態的,無需在伺服器上儲存使用者狀態。

  2. OAuth:JWT 常用於OAuth中作為訪問令牌,與OAuth的授權流程緊密結合。相比OAuth的複雜性,JWT本身更簡潔。

七、總結

JWT(JSON Web Token)是一種基於JSON的輕量級令牌,用於在客戶端和伺服器之間安全傳遞資訊。透過它的三部分結構(頭部、載荷和簽名),JWT確保資料的完整性和安全性。在現代Web開發中,JWT廣泛用於身份驗證和授權,特別是在微服務和跨域應用場景中。

相關文章