dtlc84438 2018-09-22 19:39
浏览 997
已采纳

dgrijalva / jwt-go可以对MapClaims提出主张,但不能对StandardClaims提出主张吗?

I am creating the token with the following code

token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.StandardClaims{
    Subject: string(user.Id),
})

tokenString, err := token.SignedString([]byte("secret"))

and trying to parse them with the following code

token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
    if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
        return nil, UnauthorizedError
    }

    return []byte("secret"), nil
})
if err != nil {
    return -1, UnauthorizedError
}

if !token.Valid {
    return -1, UnauthorizedError
}

claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
    return -1, UnauthorizedError
}

logrus.Info(claims)

Why can I not cast my claims to StandardClaims and access claims.Subject?

  • 写回答

1条回答 默认 最新

  • duanlu9970 2018-09-22 22:26
    关注

    Why can I not cast my claims to StandardClaims and access claims.Subject?

    Conceptually, this is not possible because the jwt.Parse function by default parses claims into an instance of jwt.MapClaims. This is a fundamentally different data structure to jwt.StandardClaims; there is no way the compiler can automatically convert between the two using a simple type conversion as they represent the data differently.

    Resolution

    The library provides the ParseWithClaims function, which allows you to specify your own implementer of the jwt.Claims interface for claims to be decoded into. You can pass an instance of jwt.StandardClaims. For example:

    token, err := jwt.ParseWithClaims(
        tokenString, &jwt.StandardClaims{},
        func(token *jwt.Token) (interface{}, error) {
            // ...
        },
    )
    

    If possible, the claims will be parsed and decoded into the variable token.Claims. The underlying (dynamic1) type of the value stored into this variable will be *jwt.StandardClaims. This can be used in a type assertion to recover the standard claims from the interface type:

    claims, ok := token.Claims.(*jwt.StandardClaims)
    if !ok {
        // handle type assertion failure
    }
    // do something with "claims"
    

    Let's dig into the language specification and library definition some more to provide a more rigorous assessment of this claim.

    Background understanding of package types

    jwt.MapClaims is a defined type with underlying type map[string]interface{} (code).

    jwt.StandardClaims is a defined struct type (code):

    type StandardClaims struct {
        // Field set elided for brevity, as it is unimportant to the
        // answer.
    }
    

    Both types implement the jwt.Claims interface type (definition), so is assignable to a variable of type jwt.Claims:

    type Claims interface {
        Valid() bool
    }
    

    The Token struct has a field called Claims of type jwt.Claims – any value which implements the Claims interface can be assigned to Claims.

    Type assertion definition

    The language spec specifies for a type assertion expression of the form x.(T) to be valid when T is not an interface type, the dynamic type1 of x must be identical to the type T. Here, you wish to evaluate the assertion x.(*jwt.StandardClaims); i.e. the asserted type is not an interface type.

    The code for jwt.Parse eventually calls jwt.ParseWithClaims on the default parser, passing in an instance of jwt.MapClaims for the claims destination:

    func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
        return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
    }
    

    so the dynamic type of the Claims field in your resulting token is of type jwt.MapClaims. This type is different (i.e. not identical) to the type jwt.StandardClaims, because user-defined types are always different from any other type except themselves. Hence, the type assertion fails.


    1Dynamic types (ref): recall in Go that interface types are fulfilled implicitly by any type which implements a super-set of the methods specified in an interface. If we define an interface of type MyInterface, the variable declaration var x MyInterface has static type (defined at compile time) MyInterface. However, at runtime, we can assign any value which implements MyInterface to x. The underlying type of the value assigned to x at any moment (the type which implements the interface) specifies the dynamic type of the variable.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 微带串馈天线阵列每个阵元宽度计算
  • ¥15 keil的map文件中Image component sizes各项意思
  • ¥30 BC260Y用MQTT向阿里云发布主题消息一直错误
  • ¥20 求个正点原子stm32f407开发版的贪吃蛇游戏
  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM
  • ¥15 划分vlan后不通了
  • ¥20 用雷电模拟器安装百达屋apk一直闪退