Session vs Token
Два подхода к auth: stateful сессии в БД или stateless JWT-токены. Каждый со своими trade-offs. Modern-выбор — часто гибрид.
Сессии (stateful)
Клиент → сервер: логин
Сервер: создаёт session_id, хранит в БД/Redis
Сервер → клиент: Set-Cookie: session_id=abc; HttpOnly; Secure
Клиент → сервер: запросы с кукой
Сервер: lookup session_id в БД → user
JWT-токены (stateless)
Клиент → сервер: логин
Сервер: подписывает JWT { sub, exp }
Сервер → клиент: токен
Клиент → сервер: Authorization: Bearer <JWT>
Сервер: проверяет подпись, читает claims — БД не нужна
Сравнение
| Сессия | JWT | |
|---|---|---|
| Хранение сервером | нужен Redis/БД | не нужно |
| Мгновенный logout | удалил из БД | требует revocation list |
| Смена прав | меняешь в БД | до истечения токена — старые права |
| Многосерверный setup | нужен shared storage | каждый сервис проверяет сам |
| Размер запроса | 32 байта cookie | 500-2000 байт header |
| CSRF | уязвим без SameSite | Bearer не автосабмитится |
| XSS-кража | HttpOnly защищает | зависит от хранения |
| Дебаг | видишь всё в БД | нужно декодить |
Гибрид (best practice)
- Внутренний auth — session cookie (HttpOnly, Secure, SameSite=Lax)
- Внешние API / микросервисы — short-lived JWT из session
- Обновление JWT из сессии как из refresh token
Мнение Стюарта Кросса
Stop using JWT for sessions.Sven Slootweg, 2016
Аргумент: JWT добавляет сложность, не даёт мгновенный logout, размером больше. Для одного монолита — сессия проще и безопаснее.
Когда JWT реально нужен
- Machine-to-machine между микросервисами
- Federation (SSO через несколько доменов)
- OIDC — id_token обязателен как JWT
- Полностью serverless без shared state