JWT-токен: принцип использования

В этой статье речь пойдет о смысле JWT-токена. А о том, как именно его настроить будет в следующей.

Общая картина

  1. Клиент вводит логин и пароль.
  2. Сервер проверяет их, и если они верны, высылает в ответе JWT-токен.
  3. Далее клиент высылает JWT-токен при каждом последующем запросе к серверу в заголовке Authorization
  4. Сервер проверяет JWT-токен на подлинность.
  5. И высылает ответ.

 

Картина в целом
Картина в целом

JWT токен vs Simple Hash-Based Remember-Me токен

JWT-токен  (JSON Web Token) похож на Simple Hash-Based Remember-Me токен, рассмотренный в предыдущей статье (только для использования JWT-токена кода потребуется написать больше):

  1. Выдается он клиенту после успешного ввода имени и пароля.
  2. С последующими запросами клиент отправляет его серверу в заголовке, сервер проверяет его подлинность путем простой калькуляции. Удостоверяется что клиент есть  тот, за кого себя выдает.
  3. JWT-токен продолжает работать и после того, как сервер перезапущен.
  4. JWT-токен работает, если серверов несколько (с балансировщиком нагрузки). На конкретный сервер ничего не завязано: сессий нет, данных, хранящихся в сессии нет.

    Несколько серверов с балансировщиком нагрузки - ок
    Несколько серверов с балансировщиком нагрузки – ок

Есть и отличия:

  1. В JWT-токене можно хранить больше данных, чем в Simple Hash-Based Remember-Me токене. В JWT-токене есть специальная часть Payload – полезная нагрузка, туда можно записать роли, например. Но можно и обойтись. Обычно достаточно имени пользователя. Ничего секретного в Payload записывать нельзя.
  2. Чтобы JWT-токен использовать в Spring Security, потребуется написать больше кода, чем с Remember-Me (тут настройка была минимальна).
  3. Для вычисления подписи в JWT-токене не используется пароль пользователя.

Поскольку сессий нет, статус взаимодействия клиента и сервера хранится на клиенте, а не на сервере (на сервере состояние хранить негде).

Структура JWT

Как показано на официальном сайте (с удобной песочницей), JWT состоит из трех частей, разделенных точкой:

  • заголовок (красный)
  • полезная нагрузка (фиолетовый)
  • подпись (голубой)
Структура JWT

Заголовок и полезная нагрузка по сути передаются в открытом виде, хоть и выглядят как непонятные символы. Это формат base64, если вставить символы в любой онлайн-декодер, то получим исходник.

Вот третья часть – хеш, или подпись, как раз и является фишкой, гарантирующей подлинность токена. Из нее не получить “исходник”, только наоборот: из исходника подпись можно получить. Что приложение и делает, именно так проверяется подлинность токена.

Как проверяется подлинность токена

Берется заголовок, полезная нагрузка и секретный ключ, их них вычисляется некоторое значение – подпись.

Секретный ключ хранится на стороне сервера. С помощью него подпись вычисляется при первоначальной выдаче токена, и с помощью него же перевычисляется каждый раз, когда приходит токен (иначе говоря, токен проверяется на валидность). Если значение вычисленной подписи совпадает с тем, что в токене, то токен считается валидным.  Это принцип поверки, аналогичный тому, что используется с Simple Hash-Based Remember-Me токеном. Только как видите, для JWT не надо даже обращаться к базе и находить пароль пользователя, чтобы вычислить подпись. Пароль в калькуляцию не входит, формула такая:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  секретный_ключ
)

Важно понять, что JWT-токен на сервере не хранится, а просто каждый раз проверяется на подлинность с помощью вышеприведенной формулы.

Хранится только секретный ключ – он един для всех JWT-токенов, выпускаемых приложением.

В каком заголовке передается JWT-токен

Принято передавать его так:

Authorization: Bearer <token>

В следующей статье будет пример приложения с JWT-токеном.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *