dgrijalva / jwt-go может выдвигать претензии к MapClaims, но не к StandardClaims? - PullRequest
0 голосов
/ 22 сентября 2018

Я создаю токен со следующим кодом

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

1 Ответ

0 голосов
/ 23 сентября 2018

Почему я не могу привести свои претензии к 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не тип интерфейса, динамический тип 1 из xдолжен быть идентичным типу 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 в любой момент (тип, реализующий интерфейс), определяет динамический тип переменной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...