errsignatureinvalid 表示签名验证失败,90% 原因为密钥不匹配或算法不一致:密钥类型错误(字符串 vs []byte)、hs256/rs256 混用、token.method 未校验、token 被前端添加 "bearer " 前缀未截取。

jwt.ParseWithClaims 为什么总返回 ErrSignatureInvalid
这不是签名算法不匹配就是密钥没对上,90% 的问题出在这儿。常见错误包括:
• 用 jwt.Parse() 解析带自定义结构体的 token,但没传 Claims 类型指针,导致类型断言失败
• 密钥用了字符串直接比较(比如 "mykey"),而实际需要 []byte("mykey")
• 签名方法写错:SigningMethodHS256 和 SigningMethodRS256 混用,或校验时没检查 token.Method
• Token 字符串被前端多加了 "Bearer " 前缀但后端没截掉,导致解析失败
如何在 Gin 中安全提取并传递用户角色
别把 Claims 直接塞进 context 后就不管了——中间件里必须先验证 token.Valid,再取值。否则攻击者构造过期或篡改的 token,仍可能触发后续逻辑。
• 使用 c.Set("user_id", claims.UserID) 和 c.Set("role", claims.Role),而不是整个 Claims 结构体
• 在权限校验路由里,用 c.MustGet("role").(string) 强转,避免 panic;建议配合 ok 判断
• 如果角色字段来自数据库(比如管理员/普通用户),不要只信 token 里的 role,应结合用户 ID 查库确认权限是否已变更
为什么不能把 jwtKey 写死在代码里
硬编码密钥等于把门锁钥匙贴在门上。线上环境必须从环境变量或 KMS 读取:
• os.Getenv("JWT_SECRET_KEY") 至少比明文好一点,但别忘了做非空校验
• 如果用 SigningMethodRS256,私钥必须严格保护,绝不能进 Git;公钥可暴露给校验方
• 开发环境可用随机生成的 key(如 openssl rand -hex 32),但上线前必须替换
• 多实例部署时,所有服务节点必须共享同一密钥,否则 A 节点签发的 token,B 节点无法验证
Refresh Token 机制最容易漏掉的两个细节
单纯延长 access token 过期时间不是刷新,那是埋雷。
• refresh token 必须单独存储(如 Redis),绑定 user_id + fingerprint(UA + IP 哈希),且设短过期(比如 7 天)
• 每次用 refresh token 换新 access token 时,要作废旧的 refresh token(或滚动更新),否则被盗用后能无限续期
• 不要在 JWT payload 里放 refresh token,它不该是自包含的——它的存在本身就要服务端可撤销
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











