JWT实战疑问

想巩固一下学到的东西,就想动手写一个注册登录的小项目,结果在JWT鉴权过程中卡住了,问题如下:
POST访问/login获得token,随后携带tokenGET访问/token使用工具验证token正常签发,然后在i鉴权中间件里走了Authorization token is wrong分支,请问这是为什么?
另外有个小问题就是,签发的token仅仅丢到了客户端,不需要保存吗?

JWT实战疑问

  • package: github.com/golang-jwt/jwt/v5

model

type User struct {
    *gorm.Model
    UserName string `form:"userName"`
    PassWord string `form:"passWord"`
}

JWT SignedToken

func (j *JWT) Signed(user *models.User) string {
    v, _ := vp.GetCfg()
    key := v.GetString("kwt.key")

    sg := jwt.NewWithClaims(jwt.SigningMethodHS256, &ArkClaims{
        MapClaims: jwt.MapClaims{
            "iss": "ark",                            // 签发者
            "sub": user.UserName,                    // 受众
            "iat": time.Now().Unix(),                // 签发时间
            "exp": time.Now().Add(time.Hour).Unix(), // 过期时间
        },
    })
    token, _ := sg.SignedString([]byte(key))

    return token
}

JWT AuthToken

func (j *JWT) Auth(tokenString string) error {
    vi, _ := vp.GetCfg()
    key := vi.GetString("jwt.key")

    token, _ := jwt.ParseWithClaims(tokenString, &ArkClaims{}, func(token *jwt.Token) (interface{}, error) {
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
        }
        return key, nil
    })
    if !token.Valid {
        return errors.New("token not valid")
    }
    return nil
}

Auth Middlware

func AuthMiddleware() gin.HandlerFunc {
    return func(ctx *gin.Context) {

        // 获取请求头中的 Authorization
        BearerToken := ctx.GetHeader("Authorization")
        if BearerToken == "" {
            ctx.JSON(http.StatusUnauthorized, gin.H{
                "msg": "Authorization token is missing",
            })
            ctx.Abort()
            return
        }
        token := BearerToken[len("Bearer "):]
        fmt.Println(token)

        // 验证 token 是否有效
        newJWT := auth.NewJWT()
        err := newJWT.Auth(token)
        if err != nil {
            ctx.JSON(http.StatusUnauthorized, gin.H{
                "msg": "Authorization token is wrong",
            })
            ctx.Abort()
            return
        }

        ctx.Next()
    }
}
最佳答案

你先别忽略err,这是官方的实例,看下err到底是什么

token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
    return []byte("AllYourBase"), nil
})

if token.Valid {
    fmt.Println("You look nice today")
} else if errors.Is(err, jwt.ErrTokenMalformed) {
    fmt.Println("That's not even a token")
} else if errors.Is(err, jwt.ErrTokenSignatureInvalid) {
    // Invalid signature
    fmt.Println("Invalid signature")
} else if errors.Is(err, jwt.ErrTokenExpired) || errors.Is(err, jwt.ErrTokenNotValidYet) {
    // Token is either expired or not active yet
    fmt.Println("Timing is everything")
} else {
    fmt.Println("Couldn't handle this token:", err)
}
1年前 评论
Scrooge (楼主) 1年前
Scrooge (楼主) 1年前
讨论数量: 9

你都知道他进入wrong分支了,怎么不打印一下err看看是哪一步错了吗,token是不需要存的,本质是个加密串,后台获取后能解出来

1年前 评论
Scrooge (楼主) 1年前
Asuna (作者) 1年前
Scrooge (楼主) 1年前

你先别忽略err,这是官方的实例,看下err到底是什么

token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
    return []byte("AllYourBase"), nil
})

if token.Valid {
    fmt.Println("You look nice today")
} else if errors.Is(err, jwt.ErrTokenMalformed) {
    fmt.Println("That's not even a token")
} else if errors.Is(err, jwt.ErrTokenSignatureInvalid) {
    // Invalid signature
    fmt.Println("Invalid signature")
} else if errors.Is(err, jwt.ErrTokenExpired) || errors.Is(err, jwt.ErrTokenNotValidYet) {
    // Token is either expired or not active yet
    fmt.Println("Timing is everything")
} else {
    fmt.Println("Couldn't handle this token:", err)
}
1年前 评论
Scrooge (楼主) 1年前
Scrooge (楼主) 1年前

找到问题了,签发的时候使用的密钥是 []byte(key),而验证的时候直接用了key,导致密钥不同。真是粗心大意。谢谢各位的解答。

1年前 评论
wangchunbo 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!