JWT
JWT — веб-токен в формате JSON
TL;DR
JWT (JSON Web Token) — формат токена с утверждениями (claims) и цифровой подписью для stateless-авторизации между клиентом и сервером. Позволяет передавать данные пользователя без сессий на сервере.
Краткое определение
JWT — компактный формат токена, который содержит набор утверждений (claims) о пользователе и может быть подписан (а иногда и зашифрован) для безопасной передачи между клиентом и сервером.
Оригинал и перевод
- Язык: английский
- Оригинал: JWT
- Расшифровка: JSON Web Token
- Буквальный перевод: веб-токен JSON
- Произношение: «джот» (англ. /dʒɒt/)
Синонимы и варианты написания
- JSON Web Token
- Access token
- Bearer token
- Веб-токен
Структура JWT токена
JWT состоит из трёх частей, разделённых точкой:
header.payload.signature eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
1. Header (заголовок)
{
"alg": "HS256",
"typ": "JWT"
}
alg— алгоритм подписи (HS256, RS256, ES256)typ— тип токена (JWT)
2. Payload (полезная нагрузка)
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622
}
Стандартные claims:
sub(subject) — идентификатор субъектаiat(issued at) — время выпуска токенаexp(expiration time) — время истеченияiss(issuer) — эмитент токенаaud(audience) — получатель токена
3. Signature (подпись)
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
Подпись гарантирует, что токен не был изменён.
Где используется
- REST API: авторизация через
Authorization: Bearer <token> - SPA приложения: React, Vue, Angular + backend API
- Микросервисы: передача контекста пользователя между сервисами
- Mobile приложения: авторизация в мобильных API
- Serverless функции: stateless аутентификация
- SSO (Single Sign-On): единый вход между системами
Когда это важно
JWT критичен в следующих сценариях:
- Stateless архитектура — нет сессий на сервере, масштабирование через load balancer
- Микросервисы — токен передаётся между сервисами без обращения к базе
- Mobile API — токены работают лучше cookies в мобильных приложениях
- Cross-domain авторизация — один токен для нескольких доменов
Как работает JWT авторизация
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Клиент │ │ Сервер │ │ База │
│ (браузер) │ │ (API) │ │ данных │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ POST /login │ │
│ {user, pass} │ │
│───────────────────>│ │
│ │ │
│ │ Проверка user/pass │
│ │───────────────────>│
│ │ │
│ │ User data │
│ │<───────────────────│
│ │ │
│ │ Генерация JWT │
│ │ (подпись) │
│ │ │
│ JWT token │ │
│<───────────────────│ │
│ │ │
│ GET /api/data │ │
│ Authorization: │ │
│ Bearer <JWT> │ │
│───────────────────>│ │
│ │ │
│ │ Проверка подписи │
│ │ (без БД!) │
│ │ │
│ Data + 200 OK │ │
│<───────────────────│ │
│ │ │
Примеры использования
Node.js (jsonwebtoken)
const jwt = require('jsonwebtoken');
// Генерация токена
const token = jwt.sign(
{ userId: 123, role: 'admin' }, // payload
process.env.JWT_SECRET, // секретный ключ
{ expiresIn: '1h' } // опции
);
// Проверка токена
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
console.log(decoded); // { userId: 123, role: 'admin', iat: ..., exp: ... }
} catch (err) {
// Токен невалиден или истёк
res.status(401).json({ error: 'Invalid token' });
}
PHP (firebase/php-jwt)
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$secret = 'your-secret-key';
// Генерация
$payload = [
'userId' => 123,
'role' => 'admin',
'iat' => time(),
'exp' => time() + 3600 // 1 час
];
$jwt = JWT::encode($payload, $secret, 'HS256');
// Проверка
try {
$decoded = JWT::decode($jwt, new Key($secret, 'HS256'));
echo "User ID: " . $decoded->userId;
} catch (Exception $e) {
http_response_code(401);
echo "Invalid token";
}
Отправка в запросе
GET /api/protected-resource HTTP/1.1 Host: api.example.com Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
JWT vs Session Cookies
| Параметр | JWT | Session Cookies |
|---|---|---|
| Хранение сессии | На клиенте (token) | На сервере (session ID) |
| Масштабирование | Легко (stateless) | Нужен sticky session или Redis |
| Отзыв токена | Сложно (нужен blacklist) | Легко (удалить сессию) |
| Размер | Больше (данные + подпись) | Меньше (только ID) |
| Безопасность | Зависит от реализации | Проверенная временем |
| Mobile API | Лучше | Хуже (cookies в mobile) |
Типичные ошибки безопасности
- ❌ Хранение чувствительных данных в payload — payload легко декодировать (это не шифрование!)
- ❌ Слишком долгий срок жизни — access token должен жить 15-60 минут
- ❌ Нет refresh token — пользователь не сможет перезайти без логина
- ❌ Отзыв токенов — нет механизма blacklist при компрометации
- ❌ Слабый секретный ключ — используйте минимум 256 бит для HS256
- ❌
alg: none— некоторые библиотеки принимают токены без подписи
Best practices для JWT
- ✅ Access + Refresh токены:
- Access token: 15-60 минут (для API запросов)
- Refresh token: 7-30 дней (для получения нового access)
- ✅ Храните токены правильно:
- Access token: в памяти JS (не в localStorage!)
- Refresh token: httpOnly cookie (защита от XSS)
- ✅ Проверяйте
expиiat— не доверяйте токенам без проверки времени - ✅ Используйте HTTPS — токены передаются в открытом виде
- ✅ Ведите blacklist — для отзыва при компрометации или logout
Аналоги и связанные термины
- Session cookie — классический механизм сессий
- OAuth 2.0 — протокол авторизации (может использовать JWT)
- OpenID Connect — слой идентификации над OAuth 2.0
- SAML — XML-_based альтернатива для enterprise
- PASETO — современная альтернатива JWT
Смотри также (статьи на сайте)
- Безопасность веб-приложений — защита от уязвимостей
- PHP 8.3-8.4: типизация и паттерны — современные подходы
Смотри также (сниппеты)
- Защита wp-login: rate-limit — защита форм авторизации
- Безопасный AJAX endpoint — проверка CSRF и сессии
Смотри также (термины)
- OAuth — протокол авторизации
- CORS — кросс-доменные запросы
- CSRF — межсайтовая подделка запросов
- Идемпотентность — свойство операций
Мини-FAQ
JWT заменяет сессии?
Ответ: Может использоваться вместо серверных сессий в stateless-сценариях. Но отзыв и инвалидация токенов сложнее, чем с сессиями.
Можно ли хранить JWT в localStorage?
Ответ: Не рекомендуется. localStorage доступен через JavaScript (XSS атака). Лучше: access token в памяти, refresh token в httpOnly cookie.
Как отозвать JWT токен?
Ответ: Варианты:
- Вести blacklist отозванных токенов (Redis)
- Использовать короткий срок жизни + refresh tokens
- Менять секретный ключ (отзовёт все токены)
JWT и шифрование — одно и то же?
Ответ: Нет. JWT подписан (проверка целостности), но не зашифрован (данные видны). Для шифрования используйте JWE (JWT Encrypted).
Какой алгоритм выбрать?
Ответ:
- HS256 — простой, быстрый (общий секрет)
- RS256 — асимметричный (публичный/приватный ключ), лучше для микросервисов
- ES256 — на эллиптических кривых, короче подпись