Что такое JWT, какова его структура и для чего он используется?

Ответ

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

Структура JWT

JWT состоит из трех частей, разделенных точками (.):


  1. Header (Заголовок): Содержит метаданные о токене. Как правило, это тип токена (typ: "JWT") и используемый алгоритм подписи (alg: "HS256", "RS256" и т.д.).

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



  2. Payload (Полезная нагрузка): Содержит утверждения (claims) — информацию о пользователе (например, user_id, roles) и другие метаданные (например, exp — время истечения срока действия токена, iat — время создания).

    {"user_id": 123, "exp": 1672521600}



  3. Signature (Подпись): Используется для проверки того, что токен не был изменен. Она создается путем подписи закодированных Header и Payload с использованием секрета (для HMAC) или приватного ключа (для RSA).


Ключевые преимущества

  • Stateless (Отсутствие состояния на сервере): Серверу не нужно хранить информацию о сессиях. Вся необходимая информация содержится в самом токене. Это упрощает масштабирование.
  • Самодостаточность: Токен содержит все данные для проверки прав доступа пользователя, что снижает количество обращений к базе данных.
  • Безопасность: Подпись гарантирует целостность данных. Важно: данные в Payload не шифруются, а кодируются в Base64Url, поэтому их может прочитать любой. Никогда не храните в JWT конфиденциальную информацию!

Пример создания в Go

import (
    "time"
    "github.com/golang-jwt/jwt/v5"
)

// Для типобезопасности лучше использовать свою структуру для claims
    type AppClaims struct {
        UserID int `json:"user_id"`
        jwt.RegisteredClaims
    }

func createToken(userID int, secret string) (string, error) {
    // Создаем claims с указанием ID пользователя и времени жизни токена
    claims := AppClaims{
        UserID: userID,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
        },
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

    // Подписываем токен секретным ключом
    return token.SignedString([]byte(secret))
}

Основные сценарии использования

  • Аутентификация: После входа пользователя сервер выдает JWT, который клиент прикрепляет к каждому последующему запросу.
  • Авторизация: В Payload можно хранить роли и права пользователя.
  • Обмен информацией: Безопасная передача данных между сервисами в микросервисной архитектуре.