簡體   English   中英

dgrijalva/jwt-go 可以將聲明轉換為 MapClaims 而不是 StandardClaims?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM