Сессии, 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 с идентификатором сессии — это фактически ключ от аккаунта, поэтому его защищают флагами:

ФлагЧто делает
HttpOnlycookie недоступна JavaScript — защита от кражи через XSS
Securecookie шлётся только по 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 даёт ограниченный доступ к данным без передачи пароля.
Проверьте себя
1. Что защищает флаг HttpOnly у cookie?
AШифрует содержимое cookie
BЗапрещает доступ к cookie из JavaScript, снижая ущерб от XSS
CОтправляет cookie только по HTTPS
DУдаляет cookie после закрытия вкладки
2. Что верно про данные внутри JWT?
AОни зашифрованы и нечитаемы
BОни подписаны, но не зашифрованы — читать может любой, подделать нет
CОни доступны только серверу
DОни хранятся на сервере, а не у клиента
3. В чём суть OAuth при входе «через Google»?
AGoogle присылает приложению ваш пароль
BПриложение получает ограниченный токен доступа без вашего пароля
CВы создаёте новый пароль для приложения
DПриложение хранит ваш пароль от Google
4. Почему JWT-токенам обычно ставят короткий срок жизни?
AЧтобы экономить трафик
BПотому что отозвать самодостаточный токен до истечения сложно
CЧтобы пользователь чаще вводил пароль ради удобства
DЭто требование HTTPS
Поддержать проект