核心概念
Access Token、Refresh ID、裝置綁定、透明刷新與撤銷如何協同運作。
Token 配對
| Token | 儲存位置 | 預設期限 | 角色 |
|---|---|---|---|
| Access Token | Cookie access_token 或 Authorization: Bearer |
15 分鐘 | 短效 ES256 JWT,承載使用者 claims |
| Refresh ID | Cookie refresh_id 或標頭 X-Refresh-ID |
7 天 | Redis 中的不透明工作階段鍵(refresh:{id}) |
Create 簽署 Access Token、產生 Refresh ID、寫入兩個 Cookie,並以 transaction pipeline 將 RefreshData 與 JTI 鍵存入 Redis。
裝置指紋
每個工作階段綁定由 OS、瀏覽器與裝置 ID 衍生的指紋(SHA-256)。驗證與刷新時會重新計算指紋,不符即拒絕,避免被竊 Token 在其他裝置使用。
可選請求標頭:
| 標頭 | 用途 |
|---|---|
X-Device-FP |
覆寫計算出的指紋 |
X-Device-ID |
參與指紋輸入的穩定裝置識別 |
透明刷新
當 Verify 發現 Access Token 缺失或過期、但仍有有效 Refresh ID 時:
- 以 SetNX 取得分散鎖(
lock:refresh:{id})。 - 從 Redis 載入
RefreshData並再次檢查指紋。 - 可選呼叫
CheckAuth確認使用者仍存在。 - 重新簽署 Access Token;若
Version超過MaxVersion,或剩餘 TTL 比例低於RefreshTTL,則完整輪換 Refresh ID。 - 更新 Redis 鍵;值變更時設定回應標頭
X-New-Access-Token/X-New-Refresh-ID。
撤銷
Revoke 清除 Cookie、縮短 Refresh ID TTL,並寫入 revoke:{accessToken},使後續驗證即使 JWT 尚未過期也會以 errorRevoked 失敗。
中介層 context
| 框架 | 中介層 | 讀取輔助 | Context 鍵 |
|---|---|---|---|
| Gin | GinMiddleware() |
GetAuthDataFromGinContext |
user |
| net/http | HTTPMiddleware(next) |
GetAuthDataFromHTTPRequest |
request.Context 的 user |
失敗時兩者皆回傳 JSON {"error": ...},狀態碼來自 JWTAuthResult。
Redis 鍵
| 模式 | 意義 |
|---|---|
refresh:%s |
Refresh ID 對應的序列化 RefreshData |
jti:%s |
作用中 Access Token 的 JTI 標記 |
lock:refresh:%s |
刷新期間的分散鎖 |
revoke:%s |
已撤銷 Access Token 標記 |
Import 路徑
函式庫原始碼位於 core/,套件名為 goJwt:
import goJwt "github.com/pardnchiu/go-jwt/core"