Cookie — один из способов хранить данные в браузере. Обзор всех способов хранения описан в статье «Хранение данных в браузере».
Кратко
СкопированоПри разработке сайтов часть информации (например, токен авторизации или данные пользователя) нужно хранить и читать как в браузере, так и на сервере. Для этого используют Cookie (произносится «куки»).
Как пользоваться
СкопированоВсе куки хранятся в свойстве document. Это свойство представляет собой строку в формате имя, где пары имён и значений разделяются знаком ; . При этом взаимодействие с полем весьма необычное — если присвоить document новое значение, то оно не заменит полностью старую строку, а добавит или изменит значение по ключу.
Запись
СкопированоЗапись в cookie работает с помощью присвоения значения новой куки в поле document. За один раз можно записать лишь одно значение.
Вот так можно добавить значение 1 по ключу counter:
document.cookie = 'counter=1'console.log(document.cookie)// 'counter=1'
document.cookie = 'counter=1'
console.log(document.cookie)
// 'counter=1'
При присвоении свойству куки с другим именем, получим два записанных значения:
document.cookie = 'sidebar=false'console.log(document.cookie)// 'counter=1; sidebar=false;'
document.cookie = 'sidebar=false'
console.log(document.cookie)
// 'counter=1; sidebar=false;'
При повторной записи в то же поле другого значения оно будет перезаписано.
document.cookie = 'sidebar=true'console.log(document.cookie)// -> 'counter=1; sidebar=true;'
document.cookie = 'sidebar=true'
console.log(document.cookie)
// -> 'counter=1; sidebar=true;'
При установке кук можно указывать не только её название и значение, но и другие параметры. Все они являются необязательными и разделяются точкой с запятой ;.
path— определяет путь, по которому будет доступна кука. Он должен быть абсолютным, то есть начинаться с/. Если параметр не передан, то кука будет доступна для текущего пути и его подпутей. Чтобы кука была доступна на всём сайте, нужно явно указать:path;= / domain— определяет домен, для которого указана кука. Если не указано, то будет использоваться текущий домен (без поддоменов). Если домен указан явно, по умолчанию кука будет доступна и для поддоменов;maxи- age expires— определяют время жизни куки.maxуказывает, через сколько секунд, а- age expiresуказывает точное время, когда кука станет недействительна. Время дляexpiresможно отформатировать с помощью встроенного метода даты;Date . toUTC String ( ) secure— указывает, что данная кука может быть передана только при запросах по защищённому протоколу HTTPS;samesite— определяет, может ли данная кука быть отправлена при кроссдоменном запросе. Значение параметраstrictбудет предотвращать отправку на другие домены, аlaxразрешит отправлять куки с GET-запросами.
Есть пара ограничений при специфичных названиях кук. Если название куки начинается с _, то обязательно должен быть передан параметр secure. При этом мы должны находиться на странице, которая была получена по HTTPS-протоколу. Если название куки начинается с _, то обязательно должны быть переданы параметры path и secure (страница также должна быть открыта по HTTPS-протоколу), а атрибут domain должен отсутствовать для снижения кроссдоменных уязвимостей.
Запись куки с разрешением передавать её только по HTTPS и только для текущего домена, со временем жизни в 1 час будет выглядеть так:
document.cookie = 'sidebar=true;secure;samesite=strict;max-age=3600'
document.cookie = 'sidebar=true;secure;samesite=strict;max-age=3600'

Чтение
СкопированоДля получения значений, записанных в куки, можно просто вывести содержимое document:
console.log(document.cookie)
console.log(document.cookie)
Учитывая, что мы уже дважды записывали куки, при вызове команды выше в консоли выведется counter.
Чтобы получить значение конкретной куки, нам нужно будет прочитать строки и разобрать её по значениям. Например, так:
function getCookie() { return document.cookie.split('; ').reduce((acc, item) => { const [name, value] = item.split('=') acc[name] = value return acc }, {})}const cookie = getCookie()console.log(cookie.counter)// 1console.log(cookie.sidebar)// true
function getCookie() {
return document.cookie.split('; ').reduce((acc, item) => {
const [name, value] = item.split('=')
acc[name] = value
return acc
}, {})
}
const cookie = getCookie()
console.log(cookie.counter)
// 1
console.log(cookie.sidebar)
// true
Удаление
СкопированоДля кук не предусмотрено специального метода удаления, поэтому для этого используется трюк с установкой кук с параметром expires который указывает на дату в прошлом. Браузер сразу же считает такую куку устаревшей и удаляет её:
document.cookie = `sidebar=;expires=${new Date(0)}`
document.cookie = `sidebar=;expires=${new Date(0)}`
В этом примере, передав число 0 в конструктор Date мы получаем время на начало эпохи Unix, а именно 1 января 1970 года. Поскольку эта дата из прошлого, то кука будет удалена моментально.
На практике
Скопированосоветует
Скопировано🛠 Есть куки, которые нельзя прочитать или записать из JavaScript. Если сервер устанавливает куки с параметром Http (доступен только для установки сервером), то такие куки будут недоступны в document. Как правило, такие куки используются для хранения чувствительной информации, как, например, токены для авторизации. Проверка авторизации происходит с помощью запроса с текущим авторизованным пользователем и считается при успешном ответе сервера.
советует
Скопировано🛠 Формат строки document не очень удобен для работы, поэтому обычно в проекте создают функции, которые упрощают чтение и запись кук. Чтобы не писать эти функции самостоятельно, можно взять библиотеку js-cookie. Это небольшая обёртка над стандартным браузерным API, которая здорово упрощает жизнь.
С этой библиотекой установка значения для куки выполняется так:
import Cookies from "js-cookie"Cookies.set("foo", "bar")
import Cookies from "js-cookie"
Cookies.set("foo", "bar")
А чтение так:
import Cookies from "js-cookie"const nameFromCookie = Cookies.get("name")
import Cookies from "js-cookie"
const nameFromCookie = Cookies.get("name")
Конечно, под капотом эта библиотека тоже работает с document, но снаружи она предоставляет простой и удобный интерфейс.