JWT时间校验需显式启用jwt.WithValidTime()并检查token.Valid;Refresh Token须独立传输通道(如X-Refresh-Token)、分离密钥、Redis单次有效存储及前端Promise共享并发刷新。

jwt.Parse 必须显式启用时间校验
很多人发现 token.Valid 总是 true,哪怕 payload 里写了 "exp"——因为 jwt.Parse 默认跳过时间验证。不加选项,token.Claims 中的 ExpiresAt 字段也不会被自动解析或校验。
正确写法是传入 jwt.WithValidTime():
token, err := jwt.Parse(tokenString, keyFunc, jwt.WithValidTime())
之后必须手动判断:if err != nil || !token.Valid,不能只看 err。否则所有过期 Token 都会被当作有效放行。
refreshToken 必须走独立 Header,且密钥分离
共用 Authorization: Bearer xxx 或同名 Cookie(如 token)会导致中间件无法区分两种 Token:要么全按 Access Token 解析失败,要么误把 Refresh Token 当 Access Token 放行,引发权限越界。
立即学习“go语言免费学习笔记(深入)”;
必须显式使用独立传输通道:
- 前端发 Refresh 请求时,用
X-Refresh-TokenHeader 传值 - 服务端用
c.Request.Header.Get("X-Refresh-Token")显式提取 -
accessSecret和refreshSecret必须是两个不同变量,不可复用同一环境变量或常量 -
ParseToken函数需带isRefresh bool参数,内部据此切换密钥与 Claims 结构
别用 jwt.MapClaims 做通用解析——它绕过结构体字段校验,容易因字段缺失或类型错位导致静默失败。
Token 消耗追踪工具。当用户需要监控 API token 使用情况、生成每日/每周消耗报告、分析使用趋势时使用此 Skill。功能包括:自动记录每次对话的 token 消耗、生成数据表格报告、计算使用趋势和预测、支持定时推送日报。
Redis 中 refreshToken 必须单次有效 + 即时失效
JWT 本身无吊销能力。若 refresh token 纯无状态(比如只签个 long-exp 字符串),泄露即等于永久通行证。
Redis Key 格式建议:refresh:{jti},值为 {user_id}:{fingerprint_hash}(fingerprint_hash 推荐用 sha256(fmt.Sprintf("%s:%s", r.UserAgent(), realIP)) 生成)。
验证流程必须严格:
- 先
GET,命中则立刻DEL(强制单次使用) - 再生成新对并写入新
jti - 新
refreshToken的exp设为 7 天,但 Redis TTL 必须严格同步该时间 - 刷新接口返回的新
refreshToken必须立即生效,旧 key 在 Redis 中已不可查——最易被忽略的是:很多实现只写入新值,却忘了删旧 key
前端 Promise 共享是并发刷新的唯一解法
点一次按钮触发多个并发请求,全卡在 401 边界。如果每个都调 /auth/refresh,服务端会生成多对新 Token,前端无法确定哪个有效,Authorization header 覆盖混乱,后续请求大概率 403。
必须维护一个全局变量 refreshPromise:
- 首次 401 时触发刷新并缓存 Promise
- 后续同批 401 全部
await refreshPromise,而非发新请求 - 刷新成功后,用新
accessToken重放原始请求;失败则清空登录态(Cookie 或内存 token)
长连接(WebSocket/gRPC)场景下,服务端需主动预推送新 Token(如 exp 前 5 分钟),不能等过期才响应。

















