Cookie: как работают
Cookie — небольшие данные, которые сервер отправляет браузеру в заголовке Set-Cookie, и браузер автоматически возвращает их при каждом следующем запросе к тому же домену.
Зачем нужно
HTTP — stateless протокол: каждый запрос независим. Куки — основной механизм сохранения состояния: идентификатор сессии, пользовательские настройки, корзина. Понимание механизма работы куки необходимо для реализации аутентификации, отладки и настройки безопасности.
Где используется
- Session ID — идентификатор серверной сессии
- Refresh Token — долгоживущий токен для обновления JWT
- Пользовательские настройки (язык, тема) без авторизации
- Аналитика (GA, Yandex Metrika) — трекинг пользователей
Жизненный цикл куки
1. Сервер устанавливает куку:
HTTP/1.1 200 OK
Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Max-Age=86400
2. Браузер сохраняет куку
3. При каждом запросе к домену — браузер добавляет заголовок:
GET /api/profile HTTP/1.1
Cookie: sessionId=abc123
4. Сервер читает куку из req.cookies.sessionId
Атрибуты куки
Set-Cookie: name=value; Path=/; Domain=example.com; Max-Age=86400; Expires=Wed, 09 Apr 2026 00:00:00 GMT; HttpOnly; Secure; SameSite=Lax
| Атрибут | Описание |
|---|---|
Path=/ |
URL-путь, для которого действует кука |
Domain=example.com |
Домен (включает поддомены) |
Max-Age=86400 |
Время жизни в секундах |
Expires=... |
Дата истечения (UTC) |
HttpOnly |
Недоступна через document.cookie |
Secure |
Только по HTTPS |
SameSite=Lax/Strict/None |
Контроль кросс-сайт отправки |
Работа с куками
Сервер (Express)
const cookieParser = require('cookie-parser');
app.use(cookieParser(process.env.COOKIE_SECRET));
// Установка
app.get('/login', (req, res) => {
res.cookie('sessionId', 'abc123', {
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: 24 * 60 * 60 * 1000, // 24 часа в мс
path: '/',
});
res.json({ ok: true });
});
// Чтение
app.get('/profile', (req, res) => {
const sessionId = req.cookies.sessionId;
// Подписанная кука (защита от подделки)
const signed = req.signedCookies.sessionId;
});
// Удаление
app.post('/logout', (req, res) => {
res.clearCookie('sessionId', { path: '/' });
res.json({ ok: true });
});
Браузер (JavaScript — только не-HttpOnly куки)
// Чтение всех доступных куки
const allCookies = document.cookie; // "theme=dark; lang=ru"
// Установка (не HttpOnly, нет срока — сессионная)
document.cookie = 'theme=dark; path=/';
// С атрибутами
document.cookie = 'lang=ru; path=/; max-age=31536000; SameSite=Lax';
// Удаление (устанавливаем с истёкшей датой)
document.cookie = 'theme=; path=/; max-age=0';
// Парсинг куки в объект
const cookies = Object.fromEntries(
document.cookie.split('; ').map(c => c.split('='))
);
Чтение куки из заголовка ответа
// Из ответа fetch заголовок Set-Cookie недоступен в браузере
// (защита браузера от JS-доступа к куке)
// Куки устанавливаются браузером автоматически
const res = await fetch('/api/login', { credentials: 'include' });
// Сервер установил Set-Cookie — браузер сохранил автоматически
Частые ошибки
- Хранение секретов (паролей, токенов) без HttpOnly — XSS их похищает
- Не указывают
Path=/— кука работает только с текущего URL - Устанавливают
Domain=.example.com— кука доступна всем поддоменам (опасно) - Путают
Max-Age(секунды) иmaxAgeв Express (миллисекунды)
Связанные темы
- _MOC Сеть
- _MOC Безопасность
- Cookie -- безопасные атрибуты (HttpOnly, Secure, SameSite)
- Сессии -- серверная авторизация
- Sessions и Cookies в Express