Golang Web接口如何校验JWT合法性_鉴权校验方式说明

8次阅读

go Web校验JWT需同时解析签名并验证exp/iat等声明,须用jwt.ParseWithClaims传入具体claims结构体和匹配密钥的回调函数中间件要规范提取Bearer Token并透传claims。

Golang Web接口如何校验JWT合法性_鉴权校验方式说明

Go web接口校验JWT合法性,核心就两件事:解析签名 + 验证声明(尤其是 expiat),缺一不可。只验签名不查过期,等于给过期令牌开绿灯;只查时间不验签名,攻击者随便改个 user_id 就能越权。

jwt.ParseWithClaims 解析并校验签名和标准声明

这是最常出错的一步——很多人直接用 jwt.Parse,它默认不校验 exp/iat,导致过期 token 仍被接受。

  • 必须传入具体 claims 结构体(如自定义 CustomClaimsjwt.MapClaims),不能只传空指针
  • 密钥回调函数必须返回 []byte,且类型要匹配签名算法(如 SigningMethodHS256 对应 Hmac
  • 错误类型要细分处理:*jwt.ValidationErrorErrors 字段可位与判断是过期、未生效还是签名错误
func ParseToken(tokenStr string) (*CustomClaims, error) {     claims := &CustomClaims{}     token, err := jwt.ParseWithClaims(tokenStr, claims, func(t *jwt.Token) (interface{}, error) {         if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {             return nil, fmt.Errorf("unexpected signing method")         }         return jwtKey, nil     })     if err != nil {         if ve, ok := err.(*jwt.ValidationError); ok {             switch {             case ve.Errors&jwt.ValidationErrorExpired != 0:                 return nil, errors.New("token expired")             case ve.Errors&jwt.ValidationErrorNotValidYet != 0:                 return nil, errors.New("token not active yet")             default:                 return nil, errors.New("invalid token signature")             }         }         return nil, err     }     if !token.Valid {         return nil, errors.New("token invalid")     }     return claims, nil }

中间件中提取 Authorization: Bearer xxx 并透传用户信息

常见坑是没统一处理 header 格式,或忽略大小写、空格、前缀缺失等边界情况。

  • r.Header.Get("Authorization") 返回值可能带空格,要用 strings.TrimSpace
  • 前缀判断必须用 strings.HasPrefix(auth, "Bearer "),不能硬切 [7:](否则遇到 "bearer xxx""Bearerxxx" 就 panic)
  • 校验通过后,用 context.WithValue 存入 claims,但注意:value 类型要一致,建议封装成导出常量 key,避免字符串拼错

自定义 claims 结构体必须嵌入 jwt.RegisteredClaims(v5 推荐)

v4 中用 jwt.StandardClaims,v5 已弃用,改用 jwt.RegisteredClaims。不嵌入会导致 exp/iat 等字段无法被自动校验。

立即学习go语言免费学习笔记(深入)”;

  • 结构体字段名必须小写 + json tag,否则 MapClaims 转换会丢数据
  • 自定义字段(如 UserID)要加 json tag,否则解析后为空
  • 别在 claims 里存敏感信息(如密码、手机号),JWT 是 Base64Url 编码,不是加密
type CustomClaims struct {     UserID uint `json:"user_id"`     Role   string `json:"role"`     jwt.RegisteredClaims }

真正难的不是写对这几行代码,而是上线后面对并发刷新 token、时钟不同步、密钥轮换这些场景——比如 exp 时间戳依赖服务器本地时间,若 NTP 同步失败,整个鉴权链就不可信。这些细节,往往比语法更决定系统是否真的安全。

text=ZqhQzanResources