JWT生成必须显式设置exp字段才能有时效性,需用jwt.NewNumericDate(time.Now().Add(duration))赋值,配合jwt.WithValidate(true)和token.Valid检查确保过期校验生效。

JWT 生成时必须显式设置 exp 字段才能有时效性
Go 里用 github.com/golang-jwt/jwt/v5(推荐 v5)生成 JWT,默认不会自动加过期时间。不设 exp,token 就是永久有效的——这不是 bug,是设计使然。你得手动往 claims 里塞 exp,而且它必须是 int64 类型的 Unix 时间戳(秒级,不是毫秒)。
常见错误是直接传 time.Now().Add(1 * time.Hour) 这种 time.Time 值进去,会 panic:jwt: unable to marshal claim "exp": json: unsupported type: time.Time。
- 正确做法:用
.Unix()转成整数,例如exp := time.Now().Add(1 * time.Hour).Unix() - 别用
time.Now().UnixMilli()—— JWT 规范只认秒级exp,毫秒会导致解析失败或被忽略 - 建议把
exp和iat(签发时间)一起设,方便调试和审计
用 jwt.RegisteredClaims 构建标准 claims 更安全
手写 map 或自定义 struct 放 exp 容易漏字段、类型错、拼写错(比如写成 expire)。v5 推荐用内置的 jwt.RegisteredClaims,它已预定义好 ExpiresAt、IssuedAt、Issuer 等字段,且类型严格。
示例片段:
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
立即学习“go语言免费学习笔记(深入)”;
claims := jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
Issuer: "my-app",
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
signedString, err := token.SignedString([]byte("your-secret"))
-
jwt.NewNumericDate()是必须的包装函数,它把time.Time转成 JWT 要求的*jwt.NumericDate类型 - 别直接赋值
ExpiresAt: time.Now().Add(...).Unix()—— 类型不匹配,编译不过 - 如果要用自定义 claims,必须嵌入
jwt.RegisteredClaims,否则Parse时可能无法识别exp
签名密钥长度影响 HS256 安全性,别用短字符串
JWT 使用 SigningMethodHS256 时,底层是 HMAC-SHA256。RFC 4868 明确要求密钥长度 ≥ 32 字节(256 bit),否则抗暴力破解能力大幅下降。用 "secret" 或 "123456" 这类短字符串,等于裸奔。
- 生成安全密钥:运行
openssl rand -hex 32,得到 64 字符 hex 字符串(对应 32 字节) - 代码里用
[]byte("your-64-char-hex-string"),别用string直接转——确保字节长度准确 - 密钥绝不能硬编码在源码里,应从环境变量或 secret manager 加载
- 如果误用短密钥,token 仍能签发和验证,但攻击者几小时就能爆破出来
解析时要主动校验 exp,不能只靠库自动检查
jwt.Parse 默认会检查 exp,但前提是调用时传了 jwt.WithValidate(true)(v5 默认关)。更关键的是:即使验证通过,你也得确认返回的 *Token 的 Valid 字段为 true,否则可能因时钟偏移、签名无效等被静默放过。
- 解析后务必检查
token.Valid == true,不要只看err == nil - 时钟不同步时,
exp可能提前失效;可传jwt.WithLeeway(60)允许 60 秒误差 - 别依赖客户端传来的
exp做业务判断——服务端必须用自己的时间比对 - 如果 token 已过期,
err通常是*jwt.ValidationError,且errors.Is(err, jwt.ErrTokenExpired)可判断
时效性真正起作用的地方,不在生成那一刻,而在每次解析时的校验逻辑是否完整、是否被执行。漏掉 Valid 检查,或者没开验证选项,token 就形同虚设。

















