- Главная
- Javascript
- JS Cookie: полное руководство по управлению
JS Cookie: полное руководство по управлению
В основе HTTP лежит принцип отсутствия состояний (stateless), поэтому для сохранения данных между сессиями используются клиентские хранилища, например, cookie. Умение управлять куками с помощью JavaScript — необходимый навык для фронтенд-разработчика. В этой статье мы по шагам разберём всё: от создания до безопасности.
Что такое cookie и зачем они нужны
Это создает иллюзию «памяти» у протокола HTTP, который сам по себе ее не имеет. Представьте себе библиотеку: без читательского билета (cookie) библиотекарь каждый раз будет воспринимать вас как нового посетителя и не вспомнит, какие книги вы уже брали. Билет позволяет идентифицировать вас и «вспомнить» историю ваших действий.
Основные сценарии использования cookie
- Управление сессиями: именно благодаря кукам сайты могут запоминать, что пользователь уже вошел в систему. После ввода логина и пароля сервер создает уникальную сессию и передает ее идентификатор браузеру в виде
cookie. При последующих запросах браузер автоматически отправляет этот идентификатор, и сервер понимает, что запрос исходит от авторизованного пользователя. - Персонализация:
cookieпозволяют сайту запоминать индивидуальные настройки пользователя. Это может быть выбранный язык интерфейса, тема оформления (светлая/темная), размер шрифта, валюта, в которой отображаются цены, или товары, добавленные в корзину в интернет-магазине. - Отслеживание (трекинг): один из наиболее спорных, но широко распространенных сценариев. Сторонние
cookieиспользуются рекламными сетями и аналитическими системами для сбора информации о поведении пользователя на разных сайтах. Это позволяет показывать релевантную рекламу, но также вызывает вопросы конфиденциальности.
Несмотря на появление более современных технологий хранения данных на стороне клиента, таких как Web Storage API (localStorage и sessionStorage) и IndexedDB, cookie остаются незаменимыми в сценариях, где информация должна автоматически передаваться на сервер с каждым HTTP-запросом.
Структура и атрибуты cookie
Чтобы эффективно управлять структурой cookie, необходимо понимать, из каких частей они состоят.
Кука — это не просто строка «ключ=значение».
Она обладает целым набором атрибутов, которые определяют ее поведение, срок жизни и доступность. Каждый атрибут отделяется от другого точкой с запятой и пробелом.
Пример 1
Типичная строка Set-Cookie, которую сервер отправляет браузеру.
sessionId=a1b2c3d4e5f6; Expires=Wed, 21 Oct 2025 07:28:00 GMT; Path=/; Domain=example.com; Secure; HttpOnly; SameSite=Lax
Или представим её в виде таблицы для наглядности:
| Атрибут | Значение | Краткое описание |
|---|---|---|
| Имя=Значение | sessionId=a1b2c3d4e5f6 | Обязательная пара. Сами данные. Имя не должно содержать специальные символы (точку с запятой, запятую, пробел). |
| Expires | Wed, 21 Oct 2025 07:28:00 GMT | Дата, после которой браузер должен удалить cookie. Если не указан, кука считается сессионной и удаляется при закрытии браузера. Используется GMT-формат. |
| Max-Age | 31536000 | Альтернатива Expires. Задает время жизни cookie в секундах относительно момента установки. Например, Max-Age=3600 удалит куку через час. |
| Path | / | Определяет путь URL, для которого кука действительна. Если Path=/docs, то кука будет отправляться для страниц /docs, /docs/articles и т.д. По умолчанию — текущий путь. |
| Domain | example.com | Указывает, на каких доменах действует кука. Если задан Domain=example.com, кука будет доступна и на поддоменах (sub.example.com). |
| Secure | (без значения) | Если присутствует, кука будет отправлена на сервер только по защищенному протоколу HTTPS. Через обычное HTTP-соединение она не передается. |
| HttpOnly | без значения) | Критически важный атрибут для безопасности. Запрещает доступ к cookie из JavaScript (через document.cookie). Такие куки могут быть установлены и прочитаны только сервером, что защищает от XSS-атак. |
| SameSite | Lax / Strict / None | Управляет отправкой cookie в межсайтовых запросах. Strict блокирует отправку для всех внешних ссылок. Lax разрешает для безопасных (GET) переходов с внешних сайтов. None разрешает всегда, но требует атрибута Secure. |
Понимание этих атрибутов критически важно, так как неправильная настройка может привести либо к уязвимостям, либо к тому, что ваши cookie просто не будут работать так, как вы ожидаете.
Чтение cookie с помощью JavaScript
cookie с помощью JavaScript осуществляется через свойство document.cookie. Это свойство ведет себя не совсем обычно.Когда вы обращаетесь к нему для чтения, оно возвращает строку, содержащую все cookie, принадлежащие текущему домену и пути, за исключением тех, у которых установлен флаг HttpOnly. Возвращаемая строка имеет формат: "name1=value1; name2=value2; name3=value3".
Нам, как разработчикам, обычно нужен доступ к значению конкретной куки по её имени. Поскольку встроенного метода для этого нет, нам необходимо написать небольшую вспомогательную функцию для парсинга этой строки. Имена переменных должны быть уникальными, поэтому назовем их targetKey и cookieCollection.
Пример 2
Функция для получения значения куки по имени.
function extractCookieValue(targetKey) {
// Создаем объект для хранения результата, но можно вернуть и просто строку
const cookieCollection = document.cookie.split('; ');
const cookieMap = {};
cookieCollection.forEach(cookieEntry => {
// Разделяем пару ключ=значение
const separatorIndex = cookieEntry.indexOf('=');
const key = cookieEntry.substring(0, separatorIndex);
const value = cookieEntry.substring(separatorIndex + 1);
cookieMap[key] = value;
});
// Возвращаем значение по ключу или пустую строку, если кука не найдена
return cookieMap[targetKey] || '';
}
// Пример использования: получаем значение куки 'userTheme'
const currentTheme = extractCookieValue('userTheme');
console.log(currentTheme); // Выведет, например, 'dark'
Эта функция сначала разбивает строку по разделителю ;, а затем каждый элемент массива делит на ключ и значение по первому знаку равенства. Это надежный способ извлечения данных, который учитывает, что в значении куки тоже может встретиться символ =. Хотя существуют и однострочные решения с использованием регулярных выражений, данный подход является более читаемым и понятным для сопровождения.
Установка и создание cookie
Процесс установки и создания cookie через JavaScript также задействует свойство document.cookie.
Когда вы присваиваете значение document.cookie, вы не перезаписываете все существующие куки, а лишь добавляете новую или обновляете существующую.
Это поведение отличается от работы с обычными объектами или переменными.
Синтаксис установки куки представляет собой строку, которая включает имя, значение и необязательные атрибуты, о которых мы говорили ранее. Все атрибуты перечисляются через точку с запятой.
Пример 3
Установка простой сессионной cookie.
// Устанавливаем куку, которая будет хранить предпочтения пользователя
// Важно: для корректной работы значения лучше кодировать функцией encodeURIComponent
const userColorPreference = 'navy-blue';
const encodedColor = encodeURIComponent(userColorPreference);
document.cookie = `preferredColor=${encodedColor}; Path=/; SameSite=Lax`;
console.log('Кука установлена!');
В этом примере мы создаем куку preferredColor со значением navy-blue. Атрибут Path=/ делает её доступной на всех страницах нашего сайта. Поскольку мы не указали Expires или Max-Age, эта кука будет сессионной и исчезнет, когда пользователь закроет браузер.
Пример 4
Установка cookie с длительным сроком жизни.
function placePersistentCookie(cookieTitle, cookieContent, daysToStore) {
const currentDate = new Date();
// Устанавливаем дату истечения
currentDate.setTime(currentDate.getTime() + (daysToStore * 24 * 60 * 60 * 1000));
const expiryDateString = currentDate.toUTCString();
// Кодируем значение, чтобы избежать проблем со спецсимволами
const securedContent = encodeURIComponent(cookieContent);
// Формируем строку куки с атрибутами
document.cookie = `${cookieTitle}=${securedContent}; Expires=${expiryDateString}; Path=/; SameSite=Lax`;
}
// Используем функцию для сохранения ID корзины на 30 дней
placePersistentCookie('shoppingCartId', 'cart_12345_abcde', 30);
Функция placePersistentCookie принимает имя, значение и количество дней хранения. Она сама вычисляет дату истечения и преобразует её в нужный GMT-формат. Использование encodeURIComponent гарантирует, что наше значение не сломает строку куки, если в нем окажутся точки с запятой, запятые или пробелы.
Оживи свой сайт. Освой JavaScript!
Статичная верстка — это только скелет. Наш онлайн-курс "JavaScript с нуля до профи" даст твоим страницам мышцы и нервы. Научись создавать слайдеры, формы, интерактивные карты и получать данные с сервера.
От теории — к реальным скриптам в твоём портфолио.
Удаление cookie через JavaScript
Удаление cookie через JavaScript — это, пожалуй, самый простой процесс, если понять его логику. У нас нет специальной команды delete для кук. Вместо этого мы пользуемся механизмом их истечения срока действия.
Чтобы браузер удалил куку, нам нужно установить её заново с той же парой имя=пустоеЗначение и с датой истечения в прошлом.
Также крайне важно при удалении указывать те же атрибуты Path и Domain, с которыми кука была создана. Если кука была создана с Path=/admin, а вы попытаетесь удалить её с Path=/, то у вас ничего не выйдет, так как для браузера это будут разные куки, даже если имя совпадает.
Пример 5
Универсальная функция для удаления cookie.
function eliminateCookie(cookieIdentifier, cookiePath = '/', cookieDomain = '') {
let cookieString = `${cookieIdentifier}=; Max-Age=-99999999; Path=${cookiePath}`;
// Если указан домен, добавляем его в строку
if (cookieDomain) {
cookieString += `; Domain=${cookieDomain}`;
}
document.cookie = cookieString;
console.log(`Попытка удалить куку '${cookieIdentifier}' выполнена.`);
}
// Пример: удаляем куку 'shoppingCartId' с путем по умолчанию '/'
eliminateCookie('shoppingCartId');
// Пример: удаляем куку с указанием пути и домена (если они были заданы при создании)
// eliminateCookie('userTheme', '/settings', 'mysite.com');
В функции eliminateCookie мы используем атрибут Max-Age с отрицательным значением (-99999999). Это гарантирует, что браузер интерпретирует куку как просроченную мгновенно и удалит её. Альтернативно можно использовать Expires=Thu, 01 Jan 1970 00:00:00 GMT. Главное — убедиться, что путь и домен совпадают с исходными параметрами куки, иначе вы будете пытаться удалить «призрака», а настоящая кука останется нетронутой.
Пример использования cookie для сохранения настроек пользователя
Лучший способ понять материал — рассмотреть практический пример. Давайте создадим простой переключатель темы (светлая/темная) на сайте и будем сохранять выбор пользователя с помощью cookie для сохранения настроек. Это классическая задача персонализации.
Пример 6
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Демо сохранения темы через куки</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="theme-container">
<h1>Выберите тему оформления</h1>
<button id="activateLight" class="theme-button light">Светлая тема</button>
<button id="activateDark" class="theme-button dark">Темная тема</button>
<p>Текущая тема: <span id="currentThemeDisplay">не определена</span></p>
</div>
<script src="script.js"></script>
</body>
</html>
body.light-mode {
background-color: #ffffff;
color: #1a1a1a;
transition: background-color 0.3s;
}
body.dark-mode {
background-color: #1a1a1a;
color: #f0f0f0;
transition: background-color 0.3s;
}
.theme-container {
font-family: sans-serif;
padding: 20px;
max-width: 400px;
margin: 50px auto;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.theme-button {
padding: 10px 15px;
margin-right: 10px;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
.theme-button.light {
background-color: #e0e0e0;
color: #333;
border: 1px solid #ccc;
}
.theme-button.dark {
background-color: #333;
color: #fff;
border: 1px solid #666;
}
(function() {
// --- Вспомогательные функции для работы с куками (адаптированные под наш пример) ---
function fetchPreference(preferenceKey) {
const allCookies = document.cookie.split('; ');
const cookieRegistry = {};
allCookies.forEach(pair => {
const splitPoint = pair.indexOf('=');
if (splitPoint > 0) {
const key = pair.substring(0, splitPoint);
const val = pair.substring(splitPoint + 1);
cookieRegistry[key] = decodeURIComponent(val);
}
});
return cookieRegistry[preferenceKey] || null;
}
function storePreference(preferenceKey, preferenceValue, expirationDays = 365) {
const now = new Date();
now.setTime(now.getTime() + (expirationDays * 24 * 60 * 60 * 1000));
const expires = now.toUTCString();
const safeValue = encodeURIComponent(preferenceValue);
document.cookie = `${preferenceKey}=${safeValue}; Expires=${expires}; Path=/; SameSite=Lax`;
}
// --- Основная логика переключения темы ---
const lightButton = document.getElementById('activateLight');
const darkButton = document.getElementById('activateDark');
const themeDisplaySpan = document.getElementById('currentThemeDisplay');
const bodyElement = document.body;
const THEME_COOKIE_NAME = 'userSiteTheme';
// Функция применения темы и обновления интерфейса
function applyVisualTheme(themeName) {
// Сначала удаляем оба возможных класса темы
bodyElement.classList.remove('light-mode', 'dark-mode');
if (themeName === 'light') {
bodyElement.classList.add('light-mode');
themeDisplaySpan.textContent = 'светлая';
} else if (themeName === 'dark') {
bodyElement.classList.add('dark-mode');
themeDisplaySpan.textContent = 'темная';
} else {
themeDisplaySpan.textContent = 'не выбрана (по умолчанию светлая)';
// Если тема не определена, можно установить светлую по умолчанию без сохранения в куки
bodyElement.classList.add('light-mode');
}
}
// Загружаем сохраненную тему при загрузке страницы
const savedTheme = fetchPreference(THEME_COOKIE_NAME);
if (savedTheme) {
applyVisualTheme(savedTheme);
} else {
// Если куки нет, применяем тему по умолчанию (светлая)
applyVisualTheme('light');
}
// --- Обработчики событий ---
lightButton.addEventListener('click', () => {
applyVisualTheme('light');
storePreference(THEME_COOKIE_NAME, 'light');
console.log('Светлая тема сохранена в cookie.');
});
darkButton.addEventListener('click', () => {
applyVisualTheme('dark');
storePreference(THEME_COOKIE_NAME, 'dark');
console.log('Темная тема сохранена в cookie.');
});
})();
В этом примере мы создали полноценный цикл работы с cookie. При загрузке страницы скрипт проверяет наличие куки userSiteTheme. Если она есть, применяется соответствующая тема. При клике на кнопку тема не только применяется визуально, но и сохраняется в cookie на год. Теперь, даже если пользователь закроет браузер и откроет сайт снова, его выбор темы сохранится.
Безопасность и ограничения
cookie — это важнейший аспект, который отличает грамотного разработчика от новичка. Основные угрозы связаны с перехватом и кражей данных.- XSS (межсайтовый скриптинг): это главная угроза для
cookie, доступных через JavaScript. Если злоумышленнику удастся внедрить свой скрипт на страницу (например, через уязвимость в форме комментариев), этот скрипт сможет получить доступ кdocument.cookieи отправить все ваши куки на свой сервер. Для защиты от этого используется атрибутHttpOnly. Куки с этим флагом становятся недоступны для JavaScript и могут быть украдены только при прямом перехвате сетевого трафика. Всегда используйтеHttpOnlyдля сессионных идентификаторов и других чувствительных данных. - Перехват трафика (Man-in-the-Middle): если кука передается по незащищенному соединению HTTP, злоумышленник в той же Wi-Fi сети может перехватить её. Атрибут
Secureполностью решает эту проблему, заставляя браузер отправлять куку только по HTTPS. - Межсайтовая подделка запроса (CSRF): злоумышленник может заставить браузер пользователя отправить запрос на ваш сайт (например, для смены пароля), используя тот факт, что куки авторизации будут отправлены автоматически. Атрибут
SameSite(особенноStrictилиLax) значительно усложняет проведение таких атак, контролируя, когда куки должны прилагаться к запросам с внешних ресурсов.
Ограничения при работе с куками
- Объем: максимальный размер одной
cookieсоставляет всего 4 КБ. Это крайне мало, поэтому хранить в куках большие структуры данных (например, JSON-объекты с полной историей заказов) нельзя. Для этого существуютlocalStorage(до 5-10 МБ) илиIndexedDB. - Количество: браузеры ограничивают общее количество кук на один домен (обычно около 20-50) и общий объем (около 4-8 КБ на домен).
- Производительность: куки передаются с каждым HTTP-запросом к серверу (включая запросы на изображения, CSS, JS). Если у вас много кук большого размера, это создает лишний трафик и замедляет загрузку сайта.
Заключение
Освоив работу с JS cookie, вы сделали важный шаг к пониманию веб-разработки. Если хотите систематизировать знания и двигаться дальше, приглашаем на наш онлайн-курс «Обучение JavaScript с нуля до профи»: вы изучите синтаксис, асинхронность и современные фреймворки под руководством опытных наставников.
А если вашему бизнесу нужен надежный цифровой инструмент, вы можете заказать создание сайта у веб-студии: мы воплотим вашу идею в готовый продукт с чистым кодом и индивидуальным подходом.