Ответ
Обработка входящего JWT (JSON Web Token) включала несколько этапов валидации и извлечения данных для аутентификации и авторизации.
Стандартный поток обработки:
- Извлечение токена: Токен приходил в заголовке
Authorizationв форматеBearer <token>. Первым делом проверялось наличие и корректность этого префикса. - Парсинг и верификация: Использовалась библиотека JJWT. Ключевые проверки:
- Структура: Проверка, что токен состоит из трех частей (header.payload.signature), разделенных точками.
- Подпись (Signature): Верификация с использованием секретного ключа (HMAC) или публичного ключа (RSA), чтобы убедиться, что токен не был изменен.
- Срок действия (Expiration): Проверка claim'а
exp(expiration time). - Аудитория (Audience) и издатель (Issuer): При необходимости проверялись claims
audиiss.
- Извлечение данных (Claims): После успешной верификации из payload токена извлекалась информация о пользователе (например,
sub— subject/userId) и его роли (roles).
Пример кода на Java с использованием JJWT:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
public JwtUserInfo validateAndParseToken(String authHeader) {
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
throw new SecurityException("Missing or invalid Authorization header");
}
String jwtToken = authHeader.substring(7); // Убираем "Bearer "
Claims claims = Jwts.parserBuilder()
.setSigningKey(secretKey) // Секретный ключ для верификации подписи
.build()
.parseClaimsJws(jwtToken)
.getBody();
// Извлечение данных из claims
String userId = claims.getSubject();
List<String> roles = (List<String>) claims.get("roles");
return new JwtUserInfo(userId, roles);
}
Дополнительные меры:
- Для реализации Refresh Token использовался отдельный эндпоинт. Refresh-токены хранились в Redis с TTL для возможности их отзыва.
- В микросервисной архитектуре секретный/публичный ключ часто хранился в защищенном хранилище (например, HashiCorp Vault).