Рубрики
Без рубрики

Декодирование токена JWT в Java

Автор оригинала: baeldung.

1. Обзор

Веб-токен JSON (JWT) часто используется в безопасности REST API. Хотя токен может быть проанализирован такими фреймворками , как Spring Security OAuth , мы можем захотеть обработать токен в нашем собственном коде.

В этом уроке мы расшифруем и проверим целостность JWT .

2. Структура токена JWT

Во-первых, давайте разберемся в структуре токена JWT:

  • заголовок
  • полезная нагрузка (часто называемая телом)
  • подпись

Подпись необязательна. Допустимый токен JWT может состоять только из разделов заголовка и полезной нагрузки. Однако мы используем раздел подписи для проверки содержимого заголовка и полезной нагрузки для авторизации безопасности .

Разделы представлены в виде строк в кодировке base64 , разделенных разделителем точки (‘.’). По замыслу любой человек может декодировать токен JWT и читать содержимое разделов заголовка и полезной нагрузки. Однако нам нужен доступ к секретному ключу, используемому для создания подписи, чтобы проверить целостность токена.

Чаще всего JWT содержит “претензии”пользователя. Они представляют собой данные о пользователе, которые API может использовать для предоставления разрешений или отслеживания пользователя, предоставляющего токен. Декодирование токена позволяет приложению использовать данные, а проверка позволяет приложению доверять тому, что JWT был сгенерирован доверенным источником.

Давайте посмотрим, как мы можем декодировать и валидировать токен в Java.

3. Декодирование токена JWT

Мы можем декодировать токен с помощью встроенных функций Java.

Во-первых, давайте разделим токен на его разделы:

String[] chunks = token.split("\\.");

Следует отметить, что регулярное выражение, переданное в String.split , использует экранированный символ ‘.’ , чтобы избежать’.’, означающего “любой символ”.

Наш массив chunks теперь должен иметь 2 или 3 элемента, соответствующих разделам JWT.

Далее давайте декодируем заголовок и полезную нагрузку с помощью декодера base64:

Base64.Decoder decoder = Base64.getDecoder();

String header = new String(decoder.decode(chunks[0]));
String payload = new String(decoder.decode(chunks[1]));

Давайте запустим этот код с токеном JWT (мы можем декодировать онлайн для сравнения результатов):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJhZWxkdW5nIFVzZXIiLCJpYXQiOjE1MTYyMzkwMjJ9.qH7Zj_m3kY69kxhaQXTa-ivIpytKXXjZc1ZSmapZnGE

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

{"alg":"HS256","typ":"JWT"}{"sub":"1234567890","name":"Baeldung User","iat":1516239022}

Если в токене JWT определены только разделы заголовка и полезной нагрузки, то мы закончили и успешно декодировали информацию.

4. Проверка токена JWT

Затем мы можем проверить целостность заголовка и полезной нагрузки, чтобы убедиться, что они не были изменены с помощью раздела подписи.

4.1. Зависимости

Для проверки мы можем добавить jwst к вашему pom.xml :


    io.jsonwebtoken
    jjwt
    0.7.0

Следует отметить, что нам нужна версия этой библиотеки из версии 0.7.0 вперед.

4.2. Настройка алгоритма подписи и спецификации ключа

Чтобы начать проверку полезной нагрузки и заголовка, нам нужен как алгоритм подписи, который изначально использовался для подписи токена, так и секретный ключ:

SignatureAlgorithm sa = HS256;
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), sa.getJcaName());

В этом примере мы жестко закодировали наш алгоритм подписи в HS256. Однако мы могли бы декодировать JSON заголовка и прочитать поле algorithm , чтобы получить это значение.

Следует также отметить, что переменная secret Key является строковым представлением секретного ключа. Мы можем предоставить это вашему приложению через его конфигурацию или через REST API, предоставляемый службой, которая выпускает JWT.

4.3. Проведение Проверки

Теперь, когда у нас есть алгоритм подписи и секретный ключ, мы можем приступить к проверке. Давайте рекомбинируем заголовок и полезную нагрузку в unsigned JWT, соединив их с разделителем ‘.’:

String tokenWithoutSignature = chunks[0] + "." + chunks[1];
String signature = chunks[2];

Теперь у нас есть неподписанный токен и предоставленная подпись. Мы можем использовать библиотеку для его проверки:

DefaultJwtSignatureValidator validator = new DefaultJwtSignatureValidator(sa, secretKeySpec);

if (!validator.isValid(tokenWithoutSignature, signature)) {
    throw new Exception("Could not verify JWT token integrity!");
}

Давайте разберемся.

Сначала мы создаем валидатор с выбранным алгоритмом и секретом. Затем мы предоставляем ему неподписанные данные токена и предоставленную подпись.

Затем. валидатор генерирует новую подпись и сравнивает ее с предоставленной подписью. Если они равны, то мы проверили целостность заголовка и полезной нагрузки.

5. Заключение

В этом уроке мы рассмотрели структуру JWT и то, как декодировать его в JSON.

Затем мы использовали библиотеку для проверки целостности токена с помощью его подписи, алгоритма и секретного ключа.

Как всегда, примеры кода из этого учебника можно найти на GitHub.