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

Go中如何正确读取JWT自定义声明至结构体?解决字段值异常

问题:Go解析JWT时Admin字段始终为false,jwt.io验证正常

我用Go代码生成带自定义声明的JWT Token,其中Admin字段设为true,在jwt.io上能正常看到该字段值为true,但通过VerifyUserToken函数解析验证时,Admin字段始终是false。相关代码如下:

生成Token的代码

func GenerateUserToken(user model.User) (string, error) {
    token := jwt.New(jwt.SigningMethodHS256)
    claims := token.Claims.(jwt.MapClaims)
    claims["iss"] = ISS
    claims["func"] = "user"
    claims["userId"] = user.UserId
    claims["exp"] = time.Now().Add(time.Hour * tokenLifetime).Unix()
    claims["identities"] = user.Identities
    claims["admin"] = user.Admin
    st, err := token.SignedString(Secret)
    if err != nil {
        return "", err
    }
    return st, nil
}

验证解析Token的代码

// bearerToken should be "Bearer <JWT>"
func VerifyUserToken(bearerToken string) (*model.UserClaims, bool) {
    strArr := strings.Split(bearerToken, " ")
    if len(strArr) != 2 || strArr[0] != "Bearer" {
        return nil, false
    }
    claims, ok := VerifyToken(strArr[1])
    if ok && claims.Func != "user" {
        return nil, false
    }

    return claims, ok
}

func VerifyToken(tokenStr string) (*model.UserClaims, bool) {
    token, err := jwt.ParseWithClaims(tokenStr, &model.UserClaims{}, func (token *jwt.Token) (interface{}, error) {
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("unexpected signing method")
        }
        return Secret, nil
    })
    if err != nil {
        return nil, false
    }
    var ok bool
    var claims *model.UserClaims
    claims, ok = token.Claims.(*model.UserClaims)
    fmt.Println(claims.Admin)
    return claims, ok && token.Valid
}

结构体定义

type User struct {
    UserId string `json:"userId"`
    Email string `json:"email"`
    Identities []IdentityNoPii `json:"identities"`
    Created uint64 `json:"created"`
    Admin bool `json:"admin"`
}

type UserClaims struct {
    User
    jwt.StandardClaims
    Func string `json:"func"`
    Sub string `json:"sub"`
}

问题根源

生成Token时你将admin作为顶层声明字段,但解析用的UserClaims结构体中,Admin字段嵌套在匿名结构体User内。部分版本的JWT库在解析时,无法自动将顶层JWT声明映射到嵌套匿名结构体的字段,导致Admin被赋予默认值false。

修复方案

两种可行方案选其一即可:

方案1:将User字段移至UserClaims顶层

修改结构体,去掉嵌套直接包含所有字段,确保JWT顶层声明能直接匹配:

type UserClaims struct {
    UserId     string                `json:"userId"`
    Email      string                `json:"email"`
    Identities []IdentityNoPii       `json:"identities"`
    Created    uint64                `json:"created"`
    Admin      bool                  `json:"admin"`
    jwt.StandardClaims
    Func string `json:"func"`
    Sub  string `json:"sub"`
}

方案2:生成Token时直接使用UserClaims结构体

保持结构体不变,修改生成逻辑,用目标结构体构建Claims,确保序列化与反序列化结构完全一致:

func GenerateUserToken(user model.User) (string, error) {
    claims := &model.UserClaims{
        User: user,
        StandardClaims: jwt.StandardClaims{
            Issuer:    ISS,
            ExpiresAt: time.Now().Add(time.Hour * tokenLifetime).Unix(),
        },
        Func: "user",
    }
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString(Secret)
}

额外检查

  • 确保使用最新稳定版JWT库(推荐github.com/golang-jwt/jwt/v5,旧版github.com/dgrijalva/jwt-go已停止维护);
  • 生成Token前可加日志确认user.Admin确实为true。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 22:34:51