Пользовательские Claims
Встроенная структура Claims покрывает типичные сценарии, но бизнес-системам часто требуются дополнительные поля. Через реализацию интерфейса CustomClaims можно определить собственную структуру Claims.
Интерфейс CustomClaims
type CustomClaims interface {
GetRegisteredClaims() *RegisteredClaims
Validate() error
}Необходимо реализовать только два метода:
| Метод | Описание |
|---|---|
GetRegisteredClaims() | Возвращает стандартные JWT-поля (iss, sub, aud и т.д.) |
Validate() | Пользовательская логика валидации |
Определение пользовательских Claims
type MyClaims struct {
UserID string `json:"user_id"`
Email string `json:"email"`
Role string `json:"role"`
jwt.RegisteredClaims
}
func (c *MyClaims) GetRegisteredClaims() *jwt.RegisteredClaims {
return &c.RegisteredClaims
}
func (c *MyClaims) Validate() error {
if c.UserID == "" {
return errors.New("user_id is required")
}
if c.Email == "" {
return errors.New("email is required")
}
return nil
}Ключевые моменты
- Необходимо встроить
jwt.RegisteredClaims GetRegisteredClaims()должен возвращать указатель на встроенное полеValidate()вызывается как при создании, так и при проверке токена
Использование пользовательских Claims
Создание токена
claims := &MyClaims{
UserID: "user123",
Email: "[email protected]",
Role: "admin",
}
token, err := processor.Create(claims)Проверка в пользовательскую структуру
Используйте ValidateInto для разбора токена в пользовательскую структуру:
myClaims := &MyClaims{}
result, valid, err := processor.ValidateInto(token, myClaims)
if err != nil {
panic(err)
}
if valid {
parsed := result.(*MyClaims)
fmt.Println("UserID:", parsed.UserID)
fmt.Println("Email:", parsed.Email)
}Обновление в пользовательскую структуру
Используйте RefreshInto для обновления токена с сохранением пользовательских полей:
newToken, err := processor.RefreshInto(refreshToken, &MyClaims{})
if err != nil {
panic(err)
}Защита временных полей
RefreshInto автоматически восстанавливает временные поля Claims (IssuedAt, ExpiresAt, ID), даже в случае неудачной операции.
Различия в валидации
Встроенные *Claims и пользовательские типы проходят разные пути валидации:
| Проверка | *Claims | Пользовательский тип |
|---|---|---|
Метод Validate() | ✅ | ✅ |
| Ограничение длины строк (256 символов) | ✅ | ❌ |
| Ограничение размера массивов (100 элементов) | ✅ | ❌ |
| Обнаружение инъекционных паттернов | ✅ | ❌ |
| Фильтрация управляющих символов | ✅ | ❌ |
Ограничения полей Extra | ✅ | Неприменимо |
| Очистка строк зарегистрированных утверждений | ✅ | ✅ |
Важно
Бизнес-поля пользовательских Claims не проходят глубокую валидацию. Пожалуйста, реализуйте все необходимые проверки в методе Validate().
Дополнительный интерфейс: RateLimitKeyer
Пользовательские Claims могут реализовать интерфейс RateLimitKeyer для предоставления ключа ограничения скорости:
func (c *MyClaims) RateLimitKey() string {
return c.Email // Использование Email в качестве ключа ограничения
}Приоритет поиска ключа ограничения: Subject → *Claims.UserID → RateLimitKey().
Дальнейшие шаги
- Справочник API → Определения интерфейсов — полное определение CustomClaims
- Справочник API → Processor — методы ValidateInto / RefreshInto
- Продвинутые примеры — полный пример пользовательских Claims