Почему document cookie не работает в браузере
Сookies или куки – это данные в виде пар ключ=значение, которые хранятся в файлах на компьютере пользователя.
Для хранимых данных существуют несколько ограничений:
- Одна пара запись не должна занимать более 4Кб.
- Общее количество кук на один домен ограничивается примерно 20.
В старых браузерах navigator.cookieEnabled может быть неопределенным.
Запись в document.cookie происходит особым образом, например следующий пример обновит только данные с ключом «name», но при этом не затронет все остальные.
Max-age и Expires
max-age устанавливает время жизни куки в секундах, а параметр expires задает непосредственно дату окончания в формате RFC-822 или RFC-1123 ( Mon, 03 Jul 2021 10:00:00 GMT ).
Следующие примеры устанавливают куки name=user сроком на один месяц:
Куки сроком на год:
Параметр указывает URL-префикс пути т.е. на каких страницах будут доступны установленные куки. Значение path должно быть относительным URL (без домена).
Как правило, в качестве пути указывают корень сайта path=/ , чтобы куки были доступны на всем сайте.
Domain
Параметр указывает домен, на котором будут доступны куки, включая поддомены.
Secure
Чтение кук не совсем удобное, в JS нет нативного метода, который получит значение по ключу. Объект document.cookie возвращает все установленные значения в виде строки, например:
Удаление данных происходит путём установки новой куки с параметром max-age=-1 или expires с прошедшей датой.
Удаление всех кук сайта:
Просмотр, редактирование и удаление кук доступно в браузерах, в панелях для разработчиков:
Google Chrome
В DevTools (Windows: F12 , MacOS: ⌘ + ⌥ + i ), вкладка «Application», раздел «Storage» – «Cookies».
Mozilla Firefox
В веб-консоли (Windows: F12 , MacOS: ⌘ + ⌥ + k ), вкладка «Хранилище», раздел «Куки».
В примере выполняется сохранение выбранного пункта селекта на нескольких страницах:
Куки обычно устанавливаются веб-сервером при помощи заголовка Set-Cookie . Затем браузер будет автоматически добавлять их в (почти) каждый запрос на тот же домен при помощи заголовка Cookie .
Один из наиболее частых случаев использования куки – это аутентификация:
Мы также можем получить доступ к куки непосредственно из браузера, используя свойство document.cookie .
Куки имеют множество особенностей и тонкостей в использовании, и в этой главе мы подробно с ними разберёмся.
Чтение из document.cookie
Хранит ли ваш браузер какие-то куки с этого сайта? Посмотрим:
Значение document.cookie состоит из пар ключ=значение , разделённых ; . Каждая пара представляет собой отдельное куки.
Чтобы найти определённое куки, достаточно разбить строку из document.cookie по ; , и затем найти нужный ключ. Для этого мы можем использовать как регулярные выражения, так и функции для обработки массивов.
Оставим эту задачу читателю для самостоятельного выполнения. Кроме того, в конце этой главы вы найдёте полезные функции для работы с куки.
Запись в document.cookie
Мы можем писать в document.cookie . Но это не просто данные, а акcессор (геттер/сеттер). Присваивание обрабатывается особым образом.
Запись в document.cookie обновит только упомянутые в ней куки, но при этом не затронет все остальные.
Например, этот вызов установит куки с именем user и значением John :
Если вы запустите этот код, то, скорее всего, увидите множество куки. Это происходит, потому что операция document.cookie= перезапишет не все куки, а лишь куки с вышеупомянутым именем user .
Технически, и имя и значение куки могут состоять из любых символов, для правильного форматирования следует использовать встроенную функцию encodeURIComponent :
Существует несколько ограничений:
- После encodeURIComponent пара name=value не должна занимать более 4Кб. Таким образом, мы не можем хранить в куки большие данные.
- Общее количество куки на один домен ограничивается примерно 20+. Точное ограничение зависит от конкретного браузера.
У куки есть ряд настроек, многие из которых важны и должны быть установлены.
Эти настройки указываются после пары ключ=значение и отделены друг от друга разделителем ; , вот так:
URL-префикс пути, куки будут доступны для страниц под этим путём. Должен быть абсолютным. По умолчанию используется текущий путь.
Если куки установлено с path=/admin , то оно будет доступно на страницах /admin и /admin/something , но не на страницах /home или /adminpage .
Как правило, указывают в качестве пути корень path=/ , чтобы наше куки было доступно на всех страницах сайта.
domain
Домен, на котором доступны наши куки. На практике, однако, есть ограничения – мы не можем указать здесь какой угодно домен.
Это ограничение безопасности, чтобы мы могли хранить в куки конфиденциальные данные, предназначенные только для одного сайта.
Таким образом, опция domain позволяет нам разрешить доступ к куки для поддоменов.
expires, max-age
Чтобы помочь куки «пережить» закрытие браузера, мы можем установить значение опций expires или max-age .
- expires=Tue, 19 Jan 2038 03:14:07 GMT
Дата истечения срока действия куки, когда браузер удалит его автоматически.
Дата должна быть точно в этом формате, во временной зоне GMT. Мы можем использовать date.toUTCString , чтобы получить правильную дату. Например, мы можем установить срок действия куки на 1 день.
Если мы установим в expires прошедшую дату, то куки будет удалено.
Альтернатива expires , определяет срок действия куки в секундах с текущего момента.
Если задан ноль или отрицательное значение, то куки будет удалено:
secure
То есть, куки, по умолчанию, опираются на доменное имя, они не обращают внимания на протоколы.
samesite
Это ещё одна настройка безопасности, применяется для защиты от так называемой XSRF-атаки (межсайтовая подделка запроса).
Чтобы понять, как настройка работает и где может быть полезной, посмотрим на XSRF-атаки.
Атака XSRF
Такая атака называется межсайтовая подделка запроса (или Cross-Site Request Forgery, XSRF).
Но такая защита требует усилий на её реализацию: нам нужно убедиться, что в каждой форме есть поле с токеном, также мы должны проверить все запросы.
Настройка samesite
Параметр куки samesite предоставляет ещё один способ защиты от таких атак, который (теоретически) не должен требовать «токенов защиты xsrf».
У него есть два возможных значения:
- samesite=strict (или, что то же самое, samesite без значения)
Куки с samesite=strict никогда не отправятся, если пользователь пришёл не с этого же сайта.
Хотя есть небольшие неудобства.
Мы могли бы обойти это ограничение, используя два куки: одно куки для «общего узнавания», только для того, чтобы поздороваться: «Привет, Джон», и другое куки для операций изменения данных с samesite=strict . Тогда пользователь, пришедший на сайт, увидит приветствие, но платежи нужно инициировать с сайта банка, чтобы отправилось второе куки.
Это более мягкий вариант, который также защищает от XSRF и при этом не портит впечатление от использования сайта.
Режим Lax так же, как и strict , запрещает браузеру отправлять куки, когда запрос происходит не с сайта, но добавляет одно исключение.
Куки с samesite=lax отправляется, если два этих условия верны:
Операция осуществляет навигацию верхнего уровня (изменяет URL в адресной строке браузера).
Обычно это так, но если навигация выполняется в , то это не верхний уровень. Кроме того, JavaScript-методы для сетевых запросов не выполняют никакой навигации, поэтому они не подходят.
Таким образом, режим samesite=lax , позволяет самой распространённой операции «переход по ссылке» передавать куки. Например, открытие сайта из заметок удовлетворяет этим условиям.
Но что-то более сложное, например, сетевой запрос с другого сайта или отправка формы, теряет куки.
Если это вам подходит, то добавление samesite=lax , скорее всего, не испортит впечатление пользователей от работы с сайтом и добавит защиту.
В целом, samesite отличная настройка, но у неё есть важный недостаток:
- samesite игнорируется (не поддерживается) старыми браузерами, выпущенными до 2017 года и ранее.
Так что, если мы будем полагаться исключительно на samesite , то старые браузеры будут уязвимы.
Но мы, безусловно, можем использовать samesite вместе с другими методами защиты, такими как XSRF-токены, чтобы добавить дополнительный слой защиты, а затем, в будущем, когда старые браузеры полностью исчезнут, мы, вероятно, сможем полностью удалить XSRF-токены.
Эта настройка не имеет ничего общего с JavaScript, но мы должны упомянуть её для полноты изложения.
Эта настройка запрещает любой доступ к куки из JavaScript. Мы не можем видеть такое куки или манипулировать им с помощью document.cookie .
Эта настройка используется в качестве меры предосторожности от определённых атак, когда хакер внедряет свой собственный JavaScript-код в страницу и ждёт, когда пользователь посетит её. Это вообще не должно быть возможным, хакер не должен быть в состоянии внедрить свой код на ваш сайт, но могут быть ошибки, которые позволят хакеру сделать это.
Обычно, если такое происходит, и пользователь заходит на страницу с JavaScript-кодом хакера, то этот код выполняется и получает доступ к document.cookie , и тем самым к куки пользователя, которые содержат аутентификационную информацию. Это плохо.
Приложение: Функции для работы с куки
Вот небольшой набор функций для работы с куки, более удобных, чем ручная модификация document.cookie .
Для этого существует множество библиотек, так что они, скорее, в демонстрационных целях. Но при этом полностью рабочие.
getCookie(name)
Самый короткий способ получить доступ к куки – это использовать регулярные выражения.
Функция getCookie(name) возвращает куки с указанным name :
Здесь new RegExp генерируется динамически, чтобы находить ; name= .
Обратите внимание, значение куки кодируется, поэтому getCookie использует встроенную функцию decodeURIComponent для декодирования.
setCookie(name, value, options)
Устанавливает куки с именем name и значением value , с настройкой path=/ по умолчанию (можно изменить, чтобы добавить другие значения по умолчанию):
deleteCookie(name)
Чтобы удалить куки, мы можем установить отрицательную дату истечения срока действия:
Обратите внимание: когда мы обновляем или удаляем куки, нам следует использовать только такие же настройки пути и домена, как при установке куки.
Приложение: Сторонние куки
Куки называются сторонними, если они размещены с домена, отличающегося от страницы, которую посещает пользователь.
Естественно, некоторым пользователям не нравится, когда их отслеживают, поэтому браузеры позволяют отключать такие куки.
Кроме того, некоторые современные браузеры используют специальные политики для таких куки:
- Safari вообще не разрешает сторонние куки.
- У Firefox есть «чёрный список» сторонних доменов, чьи сторонние куки он блокирует.
Если мы загружаем скрипт со стороннего домена, например , и этот скрипт использует document.cookie , чтобы установить куки, то такое куки не является сторонним.
Если скрипт устанавливает куки, то нет разницы откуда был загружен скрипт – куки принадлежит домену текущей веб-страницы.
Приложение: GDPR
Эта тема вообще не связана с JavaScript, но следует её иметь в виду при установке куки.
В Европе существует законодательство под названием GDPR, которое устанавливает для сайтов ряд правил, обеспечивающих конфиденциальность пользователей. И одним из таких правил является требование явного разрешения от пользователя на использование отслеживающих куки.
Обратите внимание, это относится только к куки, используемым для отслеживания/идентификации/авторизации.
То есть, если мы установим куки, которые просто сохраняют некоторую информацию, но не отслеживают и не идентифицируют пользователя, то мы свободны от этого правила.
Но если мы собираемся установить куки с информацией об аутентификации или с идентификатором отслеживания, то пользователь должен явно разрешить это.
Есть два основных варианта как сайты следуют GDPR. Вы наверняка уже видели их в сети:
Если сайт хочет установить куки для отслеживания только для авторизованных пользователей.
То в регистрационной форме должен быть установлен флажок «принять политику конфиденциальности» (которая определяет, как используются куки), пользователь должен установить его, и только тогда сайт сможет использовать авторизационные куки.
Если сайт хочет установить куки для отслеживания всем пользователям.
Чтобы сделать это законно, сайт показывает модальное окно для пользователей, которые зашли в первый раз, и требует от них согласие на использование куки. Затем сайт может установить такие куки и показать пользователю содержимое страницы. Хотя это создаёт неудобства для новых посетителей – никому не нравится наблюдать модальные окна вместо контента. Но GDPR в данной ситуации требует явного согласия пользователя.
GDPR касается не только куки, но и других вопросов, связанных с конфиденциальностью, которые выходят за рамки материала этой главы.
Мой коллега столкнулся с проблемой, из-за которой в Chrome нельзя было установить NO cookie с помощью такого кода:
document.cookie = "TEST=1; expires=Tue, 14 Oct 2014 20:23:32 GMT; path=/"
Ввод document.cookie в консоль сразу после покажет результаты, как если бы я не вносил никаких изменений. При обновлении страницы файла cookie не было, поэтому он сообщал правильно, просто неправильно устанавливал.
Приведенный выше код сработал бы, если бы он открыл новое окно в режиме инкогнито и работал бы у всех остальных в целом. Я удалил все его куки с помощью инструментов разработчика, и мне все еще не удалось вручную установить куки (хотя возвращались другие, которые были установлены через заголовки сервера).
Как только он перезапустил Chrome, он начал вести себя правильно, так что, похоже, он столкнулся с какой-то странностью или ошибкой, которую больше нельзя воспроизвести.
Кто-нибудь еще столкнулся с этим? На данный момент я думаю о том, чтобы проверить, что document.cookie сообщает о том, что ожидается после настройки, а затем инициировать наш поток без файлов cookie, когда у пользователя отключены файлы cookie, когда что-то не совпадает. Я ненавижу идею делать это, поэтому любые предложения/ответы были бы замечательными.
Это воспроизводилось каждый раз до перезагрузки браузера. Это заставляет меня беспокоиться, что другой пользователь в мире может столкнуться с этим, и эффект будет довольно плохим. Разработчики решат перезапустить браузер, но я не уверен, что это сделают пользователи. Об этом можно сообщить как об ошибке в Chrome, но у меня пока недостаточно информации, поэтому мне интересно, сталкивался ли кто-нибудь еще с этим.
4 ответа
Обязательно запустите его на сервере (по крайней мере, на локальном сервере), чтобы document.cookie работал.
Если вы локально запустите этот файл в браузере. «document.cookie» не сработает.
То, как работают файлы cookie, по крайней мере, в Chrome, немного странное.
Если вам нужно изменить значение файла cookie, вам нужно добавить/установить каждый ключ один за другим.
Попробуйте это в своей консоли:
Да, он добавил ключ, а не заменил весь файл cookie на TEST=1 .
Если вам нужно удалить ключ, вы можете просто не указывать значение: TEST= .
Я надеюсь, что это избавит вас от кошмара с печеньем (это было для меня).
Странная штука
UP: почистил весь js скрипт и оставил только эту функцию и всё равно пустоту выводит :\
6 Ответ от MandarinKa02 2017-09-09 14:20:28
- MandarinKa02
- Участник
- Неактивен
Т.к. еще сильно туп в веб, похоже понял в чем причина. Я запускал свою страницу напрямую, т.е. просто открывал файл .html в браузере, что не допустимо.
Думаю проблема с куками решится когда запущу страничку через сервер.
7 Ответ от MandarinKa02 2017-09-09 19:43:20
- MandarinKa02
- Участник
- Неактивен
Вопрос решен.
Надо через сервер запускать страничку, тогда куки будут сохранятся.
У моего коллеги возникла проблема, из-за которой в Chrome нельзя было установить cookie с помощью следующего кода:
document.cookie = "TEST=1; expires=Tue, 14 Oct 2014 20:23:32 GMT; path=/"
Помещение document.cookie в консоль сразу после показало бы результаты, как будто я не вносил изменений. При обновлении страницы файл cookie отсутствовал, поэтому он правильно отображал отчеты, но не устанавливался правильно.
Приведенный выше код работал бы, если бы он открыл новое окно инкогнито и работал для всех остальных в целом. Я удалил все его куки-файлы с помощью инструментов разработчика, но мне все равно не удалось вручную установить куки-файлы (хотя вернутся другие, которые были установлены через заголовки сервера).
После того, как он перезапустил Chrome, он начал работать должным образом, поэтому, похоже, он столкнулся с какой-то причудой или ошибкой, которую больше нельзя воспроизвести.
Кто-нибудь еще сталкивался с этим? На данный момент я думаю о проверке того, что document.cookie сообщает о том, что ожидается после установки, а затем о запуске нашего потока без файлов cookie, когда пользователь имеет куки отключены, когда вещи не совпадают. Я ненавижу идею делать это, поэтому любые предложения /ответы были бы хорошими.
3 ответа
Принцип работы файлов cookie, по крайней мере, в Chrome, немного странный.
Если вам нужно изменить значение файла cookie, вам необходимо добавить /установить каждый ключ по одному .
Попробуйте это в своей консоли:
Да, он добавил ключ и не заменяет весь файл cookie на TEST=1 .
Если вам нужно удалить ключ, вы можете просто не указывать значения: TEST= .
Надеюсь, это избавит вас от кошмара печенья (это было для меня).
Убедитесь, что он запущен на сервере (хотя бы на локальном сервере), чтобы документ.cookie работал.
Если вы локально запускаете этот файл в браузере. «document.cookie» не будет работать.
Как уже упоминал другой пользователь, вы должны установить их один за другим. Эти функции могут быть полезны при разборе & применение строки cookie:
Похожие вопросы
Популярные теги
Читайте также: