一文了解 JWT Token

在實際開發中,使用令牌認證,還有其他很多好處。掌握令牌認證的原理和實現方法,是 Go 語言開發者,必備的核心技能之一。

由於 miniblog 使用 JWT Token 進行身份認證,爲了降低學習難度併爲後續代碼實現奠定基礎,本節課將介紹 JWT 的核心內容。

JWT 認證流程

學習 JWT 的最佳方式是通過其認證流程理解其原理。認證流程如下圖所示。

上圖展示了 JWT 的認證流程,具體流程如下:

  1. 客戶端(通常是前端)通過用戶名和密碼進行登錄;

  2. 服務端收到請求後會驗證用戶名和密碼,若與數據庫記錄不一致,則認證失敗,若一致,則認證通過。認證通過後,服務端會簽發一個具有有效期的 Token 並返回給客戶端;

  3. 客戶端接收到 Token 後會將其緩存,例如存儲在瀏覽器的 Cookie 或本地存儲中,方便下次調用時使用;

  4. 客戶端在之後的每次 API 請求中攜帶緩存的 Token;

  5. 服務端接收到請求後會驗證請求中攜帶的 Token,驗證通過後繼續處理業務邏輯並返回數據;

  6. 如果 Token 快過期,前端會調用 Token 刷新接口續期 Token,避免用戶再次登錄。之後,會使用續期後的 Token 發送 API 請求。

提示:

Go 項目開發中,Token 有效期通常設置爲 2 小時。

JWT Token 格式

在 JWT 中,Token 由 Header、Payload、Signature 三部分組成,中間用英文點號(.)隔開,並使用 Base64 編碼。JWT Token 示例如下:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkwNzgwMDUsImlhdCI6MTczNTQ3ODAwNSwibmJmIjoxNzM1NDc4MDA1LCJ4LXVzZXItaWQiOiJ1c2VyLXc2aXJrZyJ9.GromRG7kK90UfU_Q5iOSHs_xE-zSk0e0HLHqJQUjYMU

(1)Header 介紹

JWT Token 的 Header 中包含兩部分信息:Token 的類型和 Token 所使用的加密算法。JWT Header 示例如下:

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

上述示例表明,Token 類型是 JWT,加密算法爲 HS256alg 支持多種加密算法)。

(2)Payload 載荷介紹

Payload 中攜帶了 Token 的具體內容,其中包含一些標準字段,當然也可以添加額外字段以表達更豐富的信息。這些信息可以用於更復雜的處理場景,例如記錄請求的用戶 ID、用戶名等。標準字段包括:

Payload 示例如下所示:

{
  "id": 2,
  "userID""user-p7q78j",
  "nbf": 1527931805,
  "iat"1527931805
}

(3)Signature 簽名介紹

Signature 是 Token 的簽名部分,其生成方式如下:

密鑰相當於一個密碼,存儲在服務端,通常通過配置文件設置密鑰的值。

最終生成的 Token 如下所示:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkwNzgwMDUsImlhdCI6MTczNTQ3ODAwNSwibmJmIjoxNzM1NDc4MDA1LCJ4LXVzZXItaWQiOiJ1c2VyLXc2aXJrZyJ9.GromRG7kK90UfU_Q5iOSHs_xE-zSk0e0HLHqJQUjYMU

簽名後,服務端會返回生成的 Token。客戶端在下次請求時會攜帶該 Token,服務端收到 Token 後會解析出 header.payload,然後使用相同的加密算法和密碼對 header.payload 再次加密,並將加密後的 Token 與收到的 Token 進行比對。如果二者相同,則驗證通過;如果不相同,則返回 HTTP 401 Unauthorized 錯誤。

JWT Token 生成示例

下述代碼展示了具體如何生成一個 JWT Token,通過代碼可以詳細的瞭解 Token 生成的方式:

#!/bin/bash

# 定義Header
HEADER='{"alg":"HS256","typ":"JWT"}'

# 定義Payload
PAYLOAD='{"exp":1739078005,"iat":1735478005,"nbf":1735478005,"x-user-id":"user-w6irkg"}'

# 定義Secret(用於簽名)
SECRET="Rtg8BPKNEf2mB4mgvKONGPZZQSaJWNLijxR42qRgq0iBb5"

# 1. Base64編碼Header
HEADER_BASE64=$(echo -n "${HEADER}" | openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n')

# 2. Base64編碼Payload
PAYLOAD_BASE64=$(echo -n "${PAYLOAD}" | openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n')

# 3. 拼接Header和Payload爲簽名數據
SIGNING_INPUT="${HEADER_BASE64}.${PAYLOAD_BASE64}"

# 4. 使用HMAC SHA256算法生成簽名
SIGNATURE=$(echo -n "${SIGNING_INPUT}" | openssl dgst -sha256 -hmac "${SECRET}" -binary | openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n')

# 5. 拼接最終的JWT Token
JWT="${SIGNING_INPUT}.${SIGNATURE}"

# 輸出JWT Token
echo "Generated JWT Token:"
echo "${JWT}"
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/ZVagoxaTg2IcA5RW9vYyBQ