Что такое JWT (JSON Web Token) и для чего он используется?

Ответ

JWT (JSON Web Token) — это открытый стандарт (RFC 7519) для создания токенов доступа, которые позволяют безопасно передавать информацию между сторонами в виде компактного JSON-объекта.

Структура токена (три части, разделенные точками):

  1. Header (Заголовок): Содержит тип токена (JWT) и алгоритм подписи (например, HS256 или RS256).
    {
      "alg": "HS256",
      "typ": "JWT"
    }
  2. Payload (Полезная нагрузка): Содержит утверждения (claims) — данные о пользователе (например, sub — subject, exp — expiration time) и другую информацию.
  3. Signature (Подпись): Создается путем кодирования header и payload с использованием секретного ключа и алгоритма, указанного в header. Подпись обеспечивает целостность токена.

Типичный сценарий использования (аутентификация):

  1. Пользователь входит в систему, сервер проверяет учетные данные.
  2. Сервер создает JWT с данными пользователя (например, userId) и подписывает его.
  3. Токен отправляется клиенту (часто в заголовке Authorization: Bearer <token>).
  4. Клиент отправляет токен с каждым последующим запросом.
  5. Сервер проверяет подпись токена и извлекает данные из payload, не обращаясь к базе данных (stateless-аутентификация).

Пример создания JWT в Java (с библиотекой jjwt):

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;

public class JwtExample {
    private static final String SECRET_KEY = "mySuperSecretKey";

    public static String createToken(String username) {
        return Jwts.builder()
            .setSubject(username) // Основное утверждение (claim)
            .setIssuedAt(new Date()) // Время создания
            .setExpiration(new Date(System.currentTimeMillis() + 86400000)) // Срок действия (1 день)
            .signWith(SignatureAlgorithm.HS256, SECRET_KEY) // Подпись
            .compact(); // Генерация строки токена
    }
}

Преимущества: Стандартизация, компактность, самодостаточность (несет в себе данные), не требует хранения состояния на сервере. Недостатки/Риски: Невозможность немедленного отзыва токена (до истечения срока), критическая важность защиты секретного ключа, необходимость безопасной передачи (HTTPS).

Ответ 18+ 🔞

А, слушай, про эту вашу моду — JWT! Ну, блядь, все сейчас только о них и говорят, как будто открыли Америку, а это ж просто бумажка, но с цифровой подписью, ёпта!

Представь себе бутерброд из трёх слоёв, склеенных точками. Первый кусок — Header (Заголовок). Там написано, что это JWT и какой алгоритм подписи использовали, например, HS256. Типа, «эй, я тут, и я подписан вот так!». Кодируется в Base64URL, и всё.

{
  "alg": "HS256",
  "typ": "JWT"
}

Второй кусок — Payload (Полезная нагрузка). Вот тут-то и начинается самое интересное, блядь! Туда можно накидать любых данных о пользователе: его логин, ID, срок годности токена. Эти данные называются claims (утверждения). Например, sub — это кто, exp — когда протухнет. Можно и свою хуйню добавить, типа role: "admin". Главное — не переборщить, а то токен раздуется, как питон, сожравший кролика.

Третий, самый важный кусок — Signature (Подпись). Без неё вся эта конструкция — просто бумажка, которой подтереться. Берутся закодированные header и payload, склеиваются точкой, и эта хуйня подписывается секретным ключом с помощью выбранного алгоритма. Если кто-то попытается изменить payload — подпись не сойдётся, и сервер скажет: «Иди нахуй, мудак!».

Как это обычно работает, на пальцах:

  1. Пользователь логинится — вводит пароль, а сервер думает: «Ну, окей, похоже на правду».
  2. Сервер, вместо того чтобы заводить сессию в памяти, говорит: «А нахуй нам это? Давайте сварганим токен!». Берёт данные пользователя, лепит payload, подписывает своим секретным ключом и выдаёт клиенту.
  3. Клиент, довольный как слон, получает эту строку (типа eyJhbGciOiJIUzI1NiIsInR5c...) и тычет её в каждый следующий запрос, обычно в заголовок Authorization: Bearer <token>.
  4. Сервер, получив токен, проверяет подпись. Если всё ок — вытаскивает данные из payload и верит им, как священному писанию. Никаких обращений к базе данных для проверки сессии — красота, блядь!

Вот, смотри, как на Java (с библиотекой jjwt) это выглядит:

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;

public class JwtExample {
    private static final String SECRET_KEY = "mySuperSecretKey";

    public static String createToken(String username) {
        return Jwts.builder()
            .setSubject(username) // Основное утверждение (claim)
            .setIssuedAt(new Date()) // Время создания
            .setExpiration(new Date(System.currentTimeMillis() + 86400000)) // Срок действия (1 день)
            .signWith(SignatureAlgorithm.HS256, SECRET_KEY) // Подпись
            .compact(); // Генерация строки токена
    }
}

Плюсы, блядь, очевидны: стандарт, компактность, самодостаточность (всё в себе несёт), серверу не надо хранить состояние — ебашь себе stateless, и всё пучком.

А теперь про минусы, ёпта, их тоже дохуя:

  • Отозвать нельзя, пока не сдохнет. Выдал токен со сроком жизни в неделю — всё, поезд ушёл. Пока exp не наступит, он будет валидным. Хоть пользователя уволи, хоть он пароль смени — токен будет работать. Единственный способ — завести чёрный список, но это уже state, нахуй тогда JWT?
  • Секретный ключ — это святое. Если его скомпрометируют — пиздец всему. Все токены, когда-либо выпущенные, можно будет подделать. Хуй в пальто, а не безопасность.
  • HTTPS — обязательно! Иначе токен перехватят по дороге, и будут им пользоваться, как своим. А там в payload может и ID админа быть, представляешь?
  • Не храни в payload то, что не готов показать всему миру. Он же кодируется в Base64, а не шифруется. Любой дурак может его декодировать и прочитать. Хуй с ним, что логин, а если там номер карточки? Вот тогда удивление пиздец наступит.

В общем, инструмент мощный, но, как молоток: можно дом построить, а можно себе по яйцам дать. Думай головой, когда используешь!