[英]dgrijalva/jwt-go can cast claims to MapClaims but not 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?为什么我不能将我的声明转换为 StandardClaims 并访问 claim.Subject?
Why can I not cast my claims to
StandardClaims
and accessclaims.Subject
?为什么我不能将我的声明转换为StandardClaims
并访问claims.Subject
?
Conceptually, this is not possible because the jwt.Parse
function by default parses claims into an instance of jwt.MapClaims
.从概念上讲,这是不可能的,因为jwt.Parse
函数默认将声明解析为jwt.MapClaims
的实例。 This is a fundamentally different data structure to jwt.StandardClaims
;这是与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.编译器无法使用简单的类型转换在两者之间自动转换,因为它们表示数据的方式不同。
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.该库提供了ParseWithClaims
函数,它允许您指定自己的jwt.Claims
接口实现者,以便将声明解码为。 You can pass an instance of jwt.StandardClaims
.您可以传递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
.如果可能,声明将被解析并解码为变量token.Claims
。 The underlying (dynamic 1 ) type of the value stored into this variable will be *jwt.StandardClaims
.存储到此变量中的值的基础(动态1 )类型将是*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.让我们更深入地研究语言规范和库定义,以对该声明进行更严格的评估。
jwt.MapClaims
is a defined type with underlying type map[string]interface{}
( code ). jwt.MapClaims
是一个定义的类型,具有底层类型map[string]interface{}
( code )。
jwt.StandardClaims
is a defined struct
type ( code ): jwt.StandardClaims
是一个定义的struct
类型( 代码):
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
:这两种类型都实现了jwt.Claims
接口类型( 定义),因此可以分配给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
. Token
结构有一个名为Claims
的字段,类型为jwt.Claims
任何实现Claims
接口的值都可以分配给Claims
。
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 type 1 of x
must be identical to the type T
.语言规范指定x.(T)
形式的类型断言表达式在T
不是接口类型时有效, x
的动态类型1必须与类型T
相同。 Here, you wish to evaluate the assertion x.(*jwt.StandardClaims)
;在这里,您希望评估断言x.(*jwt.StandardClaims)
; ie 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: jwt.Parse
的代码最终在默认解析器上调用jwt.ParseWithClaims
,传入一个jwt.MapClaims
的实例作为声明目的地:
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
.所以结果令牌中Claims
字段的动态类型是jwt.MapClaims
类型。 This type is different (ie not identical) to the type jwt.StandardClaims
, because user-defined types are always different from any other type except themselves.此类型与类型jwt.StandardClaims
不同(即不相同),因为用户定义的类型总是与除自身之外的任何其他类型不同。 Hence, the type assertion fails.因此,类型断言失败。
1 Dynamic 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. 1动态类型( ref ):在 Go 中回忆一下,接口类型由实现接口中指定方法的超集的任何类型隐式实现。 If we define an interface of type MyInterface
, the variable declaration var x MyInterface
has static type (defined at compile time) MyInterface
.如果我们定义一个MyInterface
类型的接口,变量声明var x MyInterface
具有静态类型(在编译时定义) MyInterface
。 However, at runtime, we can assign any value which implements MyInterface
to x
.但是,在运行时,我们可以将实现MyInterface
任何值分配给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.任何时候分配给x
的值的基础类型(实现接口的类型)指定变量的动态类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.