You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用golang-jwt生成JWT后自定义Claims丢失问题排查

问题原因与解决方法

核心问题

你的自定义Claims结构体中userid是小写开头的字段,在Go语言里小写字段属于私有字段,golang-jwt库依赖反射机制序列化/反序列化Claims,而反射无法访问私有字段,导致userid根本没被写入JWT的payload中。解析时自然只能拿到int类型的默认值0。

解决步骤

  1. 将自定义Claims中的字段改为大写开头(公开字段),让反射机制可以访问
  2. 可选但推荐:添加json标签,指定JWT payload中对应的字段名(符合常规命名习惯)

修改后的代码示例

package main

import (
    "fmt"
    "time"

    "github.com/golang-jwt/jwt/v4"
)

// 修改字段为公开字段,添加json标签指定payload中的键名
type MyCustomClaims struct {
    UserID int `json:"userid"`
    jwt.RegisteredClaims
}

func (app *Config) generateJWT(userid int) {
    // 生成JWT
    jt := jwt.NewWithClaims(jwt.SigningMethodHS256, MyCustomClaims{
        UserID: userid,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(3 * time.Hour)),
            IssuedAt:  jwt.NewNumericDate(time.Now()),
        },
    })

    fmt.Println("What was put", jt.Claims.(MyCustomClaims).UserID)
    // 不要忽略签名错误
    token, err := jt.SignedString(app.secret)
    if err != nil {
        fmt.Println("签名失败:", err)
        return
    }

    // 解析并验证JWT
    parsedToken, err := jwt.ParseWithClaims(token, &MyCustomClaims{}, func(t *jwt.Token) (interface{}, error) {
        return app.secret, nil
    })
    if err != nil {
        fmt.Println("解析失败:", err)
        return
    }

    // 安全转换Claims类型并验证token有效性
    if claims, ok := parsedToken.Claims.(*MyCustomClaims); ok && parsedToken.Valid {
        fmt.Println("What was parsed", claims.UserID)
    } else {
        fmt.Println("无效Token或Claims类型转换失败")
    }
}

额外注意事项

  • 永远不要忽略SignedString和ParseWithClaims返回的错误,否则会隐藏签名失败、Token无效等潜在问题
  • Go的结构体字段可见性严格区分大小写,只有大写开头的字段能被包外的代码(包括反射机制)访问

内容的提问来源于stack exchange,提问作者Sushant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 13:15:58