Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Вход по токену JWT

С Basic-входом пароль летит в каждом запросе. Обычно делают иначе: клиент один раз отправляет логин и пароль на адрес входа и получает токен — строку, которая подтверждает, кто он. Дальше клиент передаёт только токен в заголовке Authorization: Bearer .... Самый распространённый формат токена — JWT (JSON Web Token): три части через точку, в середине — данные о пользователе, в конце — подпись сервера. Подделать токен без секретного ключа нельзя.

Настройки

Модуль micronaut-security-jwt уже подключён в прошлом уроке. Добавьте две строки в настройки:

# src/main/resources/application.properties
micronaut.security.authentication=bearer
micronaut.security.token.jwt.signatures.secret.generator.secret=${JWT_SECRET:changemechangemechangemechangeme}

Первая включает режим токенов: появляется адрес POST /login, а сервер принимает заголовок Bearer. Вторая задаёт секрет подписи. Запись ${JWT_SECRET:...} значит «взять из переменной окружения JWT_SECRET, а если её нет — значение после двоеточия». На сервере секрет задают только переменной.

BlogAuthenticationProvider из прошлого урока менять не нужно: /login проверяет логин и пароль через него же.

Получение токена

curl -X POST http://localhost:8080/login \
  -H "Content-Type: application/json" \
  -d '{"username":"oleg","password":"changeme"}'
{"username":"oleg","roles":["AUTHOR"],"expires_in":3600,"access_token":"eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJibG9nIiwic3ViIjoib2xlZyIsIm5iZiI6MTc5MTEwNDk5OCwiZXhwIjoxNzkxMTA4NTk4LCJpYXQiOjE3OTExMDQ5OTgsInJvbGVzIjpbIkFVVEhPUiJdfQ.wmoVIAAmS-k5aPIKf9RS7Q9FUJEgsG5FVcWJMjojLFc","token_type":"Bearer"}

Токен действует 3600 секунд — час. Средняя часть — это просто Base64, её можно прочитать:

{"iss":"blog","sub":"oleg","nbf":1791104998,"exp":1791108598,"iat":1791104998,"roles":["AUTHOR"]}

sub — имя пользователя, roles — роли, exp — время окончания. Пароля в токене нет. Сервер не хранит выданные токены: он проверяет подпись и срок.

Запросы с токеном

Сохраните токен в переменную и передайте в заголовке:

TOKEN=eyJhbGciOiJIUzI1NiJ9...
curl -X POST http://localhost:8080/articles \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"С токеном","body":"Текст"}'
{"id":1,"title":"С токеном","body":"Текст"}

Правила @Secured из прошлого урока работают так же — роли берутся из токена. Контроллер /me с параметром Authentication покажет {"name":"oleg","roles":["AUTHOR"]}.

Ответы при ошибках

СитуацияОтвет
Неверный пароль на /login401 Credentials Do Not Match
Нет токена, а метод требует входа401 Unauthorized
Токен испорчен или истёк401 Unauthorized
Токен верный, но роли не хватает403 Forbidden

Частая ошибка

Алгоритм подписи HS256 требует секрет длиной не меньше 256 бит — 32 символа. С коротким секретом, например JWT_SECRET=changeme, приложение запускается, но /login отвечает 500 с пустым телом, а в журнале:

WARN  i.m.s.t.j.g.JwtTokenGenerator - JOSEException while generating token The secret length must be at least 256 bits

Используйте длинную случайную строку и храните её вне репозитория.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.