jwt的exp字段不生效是因为v5默认关闭时间校验,必须显式传jwt.withexpirationrequired()并手动检查token.valid,否则即使过期token.valid仍为true;同时需确保服务集群ntp时间同步。

JWT 的 exp 字段不生效,不是 JWT 本身有问题,而是 Go 解析时默认跳过时间校验——jwt.ParseWithClaims 不会自动检查过期,必须显式启用并手动判断 token.Valid。
jwt.ParseWithClaims 必须传 jwt.WithExpirationRequired()
v5 版本(github.com/golang-jwt/jwt/v5)默认关闭所有时间相关校验(exp、nbf、iat)。只解析 token 并填充 claims,不验证是否过期。
- 漏掉
jwt.WithExpirationRequired()→token.Valid仍为true,哪怕已过期 - 即使写了
if !token.Valid,没启用时间校验,这个判断也毫无意义 - 正确调用示例:
token, err := jwt.ParseWithClaims( tokenStr, &MyClaims{}, func(t *jwt.Token) (interface{}, error) { return []byte(secret), nil }, jwt.WithExpirationRequired(), // ← 关键! )
Gin 中间件里 token.Valid 必须手动检查
token.Valid 是一个布尔字段,它不会在解析过程中自动计算——它只在你调用 token.Verify... 或使用带校验选项的 ParseWithClaims 后才被设置。v5 中它依赖你传入的 ParseOption 才会参与计算。
- 常见错误写法:
if err != nil { ... }就返回,忽略!token.Valid - 正确顺序:先看
err,再看token != nil && token.Valid - 注意:如果
err非空,token可能为nil,直接访问token.Valid会 panic - 安全写法:
if err != nil || token == nil || !token.Valid { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid token"}) return }
微服务集群必须统一 NTP 时间同步
JWT 过期判断基于系统本地时间。如果服务 A 和服务 B 时钟偏差超过 5 秒(JWT 默认 Leeway 是 5s),就会出现“在 A 看已过期,在 B 看还有效”的不一致。
- 现象:用户刚登出,部分服务仍接受其 token;或 token 明明刚签发,却提示“已过期”
- 排查方法:在各服务中加日志打印
time.Now().UTC().Unix()和 token 的exp值对比 - 解决方式:所有容器/VM 必须配置 NTP 客户端(如
chrony或systemd-timesyncd),指向同一内网 NTP 服务器 - 可选加固:在 Parse 时传
jwt.WithTimeFunc(func() time.Time { return time.Now().UTC() }),避免本地时区干扰
鉴权中间件容易绕过的三个典型路径
Gin 路由中间件默认不拦截 OPTIONS 预检、健康检查(如 /healthz)、静态资源(如 /swagger/*filepath),这些路径若未显式排除,就可能成为鉴权盲区。
- OPTIONS 请求:CORS 预检不走业务中间件,但某些网关或代理会转发,需单独处理:
if c.Request.Method == "OPTIONS" { c.AbortWithStatus(200); return } - 健康检查路径:应在注册路由时明确跳过中间件,例如:
r.GET("/healthz", HealthHandler),而非r.Use(AuthMiddleware).GET(...) - 静态路由:Gin 的
StaticFS默认不经过中间件,但若用Static+ 自定义 handler,需确认是否包裹了中间件链 - 额外风险点:子路由组未继承中间件,比如
api := r.Group("/api")后忘了api.Use(AuthMiddleware)
最常被忽略的是时钟同步和 token.Valid 的双重判空逻辑——前者让 exp 失效变成概率性问题,后者让整个鉴权流程形同虚设。上线前务必在多节点环境跑一次跨服务 token 传递+过期测试。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











