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