gpt4 book ai didi

go - dgrijalva/jwt-go 可以将声明转换到 MapClaims 而不是 StandardClaims?

转载 作者:IT王子 更新时间:2023-10-29 01:56:48 28 4
gpt4 key购买 nike

我正在使用以下代码创建 token

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

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

并尝试用下面的代码解析它们

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)

为什么我不能将我的声明转换到 StandardClaims 并访问 claims.Subject?

最佳答案

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

从概念上讲,这是不可能的,因为 jwt.Parse 函数 by default将声明解析为 jwt.MapClaims 的实例。这是与 jwt.StandardClaims 根本不同的数据结构;编译器无法使用简单的类型转换自动在两者之间进行转换,因为它们以不同的方式表示数据。

决议

该库提供了 ParseWithClaims 函数,它允许您指定您自己的 jwt.Claims 接口(interface)的实现者,以便将声明解码到其中。您可以传递 jwt.StandardClaims 的实例。例如:

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

如果可能,声明将被解析并解码为变量token.Claims。存储到此变量中的值的基础 (dynamic1) 类型将是 *jwt.StandardClaims。这可以在类型断言中用于从接口(interface)类型中恢复标准声明:

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

让我们进一步深入研究语言规范和库定义,以便对这一说法进行更严格的评估。

包类型的背景知识

jwt.MapClaims 是一个已定义的类型,其底层类型为 map[string]interface{} ( code )。

jwt.StandardClaims 是定义的 struct 类型 ( code ):

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

这两种类型都实现了 jwt.Claims 接口(interface)类型 ( definition ),因此可以分配给 jwt.Claims 类型的变量:

type Claims interface {
Valid() bool
}

Token 结构有一个 field称为 jwt.Claims 类型的 Claims – 任何实现 Claims 接口(interface)的值都可以分配给 Claims

类型断言定义

语言规范 specifies要使 x.(T) 形式的类型断言表达式在 T 不是接口(interface)类型时有效,动态类型x 中的 >1 必须与 T 类型相同。在这里,您希望评估断言 x.(*jwt.StandardClaims);即断言类型不是接口(interface)类型。

code对于 jwt.Parse 最终在默认解析器上调用 jwt.ParseWithClaims,为声明目标传入一个 jwt.MapClaims 实例:

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

所以生成的 token 中 Claims 字段的动态类型是 jwt.MapClaims 类型。此类型与 jwt.StandardClaims 类型不同(即不相同),因为用户定义的类型是 always different来自除他们自己以外的任何其他类型。因此,类型断言失败。


1动态类型 ( ref ):在 Go 中回想一下,接口(interface)类型由实现方法超集的任何类型隐式实现在接口(interface)中指定。如果我们定义一个MyInterface类型的接口(interface),变量声明var x MyInterface有静态类型(在编译时定义)MyInterface。但是,在运行时,我们可以将实现 MyInterface 的任何值分配给 x。任何时刻分配给 x 的值的基础类型(实现接口(interface)的类型)指定变量的动态类型

关于go - dgrijalva/jwt-go 可以将声明转换到 MapClaims 而不是 StandardClaims?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52460230/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com