Сессии, cookie, токены и OAuth
HTTP не помнит вас между запросами — поэтому после входа сервер выдаёт «пропуск», который браузер предъявляет каждый раз.
Сессия — способ сервера помнить, что данный пользователь уже вошёл, не требуя пароль на каждый запрос. Обычно опирается на cookie с идентификатором сессии.
Проблема: HTTP без памяти
Протокол HTTP не хранит состояние: каждый запрос для сервера независим. Если бы не было сессий, пришлось бы вводить пароль на каждой странице. Поэтому после успешного входа сервер выдаёт пользователю что-то, что тот будет предъявлять при следующих запросах.
Подход 1: серверные сессии и cookie
Классическая схема: сервер создаёт случайный идентификатор сессии, сохраняет связь «id → пользователь» у себя и отправляет этот id браузеру в cookie. Браузер автоматически прикладывает cookie к каждому запросу на этот сайт. Сервер по id находит пользователя.
Идентификатор сессии должен быть длинным и непредсказуемым — иначе его можно угадать. Поэтому его генерируют криптостойким генератором:
import secrets
# Идентификатор сессии: длинный, случайный, неугадываемый
session_id = secrets.token_hex(32)
print("Длина id сессии:", len(session_id), "hex-символов")
print("Это 256 бит случайности:", len(session_id) * 4, "бит")
Вывод:
Длина id сессии: 64 hex-символов Это 256 бит случайности: 256 бит
Флаги безопасности cookie
Cookie с идентификатором сессии — это фактически ключ от аккаунта, поэтому его защищают флагами:
| Флаг | Что делает |
HttpOnly | cookie недоступна JavaScript — защита от кражи через XSS |
Secure | cookie шлётся только по HTTPS — не утечёт по открытому каналу |
SameSite | ограничивает отправку cookie на чужие сайты — защита от CSRF |
Подход 2: токены и JWT
Альтернатива — выдать пользователю токен, который он сам носит и предъявляет (обычно в заголовке Authorization). Популярный формат — JWT (JSON Web Token). JWT состоит из трёх частей через точку: заголовок, полезные данные (например, id пользователя) и подпись.
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYWxpY2UifQ.<подпись>
Ключевая идея: данные в JWT не зашифрованы, а только подписаны. Любой может прочитать содержимое (это просто base64), но изменить его незаметно нельзя — подпись не сойдётся. Поэтому в JWT нельзя класть секреты, но можно класть id пользователя.
Сессии против токенов
| Свойство | Серверные сессии | JWT-токены |
| Состояние | хранится на сервере | в самом токене у клиента |
| Отзыв доступа | легко — удалить сессию | сложнее — токен живёт до истечения |
| Масштабирование | нужна общая память сессий | проще, токен самодостаточен |
Из-за сложности отзыва токенам ставят короткий срок жизни и обновляют их отдельным refresh-токеном.
OAuth кратко: «Войти через…»
Кнопка «Войти через Google» — это OAuth. Его суть: вы разрешаете одному сервису ограниченный доступ к данным в другом без передачи пароля. Приложение не видит ваш пароль от Google — оно получает от Google токен с ограниченными правами (например, «узнать имя и email»). Так пароль остаётся только у того, кто его выдал, а права можно отозвать в любой момент.
Итог
- HTTP без памяти, поэтому после входа сервер выдаёт сессию или токен.
- Идентификатор сессии живёт в cookie с флагами HttpOnly, Secure, SameSite.
- JWT подписан, но не зашифрован: читать может любой, подделать — нет; секреты в него не кладут.
- OAuth даёт ограниченный доступ к данным без передачи пароля.