![](/img/trans.png)
[英]Problem with generating jwt token RS256 with dgrijalva/jwt-go package
[英]dgrijalva/jwt-go can cast claims to MapClaims but not StandardClaims?
我正在使用以下代碼創建令牌
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 並訪問 claim.Subject?
為什么我不能將我的聲明轉換為
StandardClaims
並訪問claims.Subject
?
從概念上講,這是不可能的,因為jwt.Parse
函數默認將聲明解析為jwt.MapClaims
的實例。 這是與jwt.StandardClaims
完全不同的數據結構; 編譯器無法使用簡單的類型轉換在兩者之間自動轉換,因為它們表示數據的方式不同。
該庫提供了ParseWithClaims
函數,它允許您指定自己的jwt.Claims
接口實現者,以便將聲明解碼為。 您可以傳遞jwt.StandardClaims
的實例。 例如:
token, err := jwt.ParseWithClaims(
tokenString, &jwt.StandardClaims{},
func(token *jwt.Token) (interface{}, error) {
// ...
},
)
如果可能,聲明將被解析並解碼為變量token.Claims
。 存儲到此變量中的值的基礎(動態1 )類型將是*jwt.StandardClaims
。 這可用於類型斷言以從接口類型恢復標准聲明:
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
類型( 代碼):
type StandardClaims struct {
// Field set elided for brevity, as it is unimportant to the
// answer.
}
這兩種類型都實現了jwt.Claims
接口類型( 定義),因此可以分配給jwt.Claims
類型的變量:
type Claims interface {
Valid() bool
}
Token
結構有一個名為Claims
的字段,類型為jwt.Claims
任何實現Claims
接口的值都可以分配給Claims
。
語言規范指定x.(T)
形式的類型斷言表達式在T
不是接口類型時有效, x
的動態類型1必須與類型T
相同。 在這里,您希望評估斷言x.(*jwt.StandardClaims)
; 即斷言類型不是接口類型。
jwt.Parse
的代碼最終在默認解析器上調用jwt.ParseWithClaims
,傳入一個jwt.MapClaims
的實例作為聲明目的地:
func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
}
所以結果令牌中Claims
字段的動態類型是jwt.MapClaims
類型。 此類型與類型jwt.StandardClaims
不同(即不相同),因為用戶定義的類型總是與除自身之外的任何其他類型不同。 因此,類型斷言失敗。
1動態類型( ref ):在 Go 中回憶一下,接口類型由實現接口中指定方法的超集的任何類型隱式實現。 如果我們定義一個MyInterface
類型的接口,變量聲明var x MyInterface
具有靜態類型(在編譯時定義) MyInterface
。 但是,在運行時,我們可以將實現MyInterface
任何值分配給x
。 任何時候分配給x
的值的基礎類型(實現接口的類型)指定變量的動態類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.