Тел.: +7 (495) 749 43 55

Полезные статьи

Статьи
ИНТЕРНЕТ ТЕХНОЛОГИИ
НОВОСТИ

СТАТЬИ




Работа с cookie, объект document.cookie


Работа с cookie, объект document.cookie

В статье описываются принципы работы с cookie в клиентских сценариях, написанных на языке JavaScript при помощи использования объекта document.cookie.

Введение

Механизм закладок (cookie) является составной частью HTTP-протокола. Данный механизм позволяет производить сохранение небольших количеств информации, переданных сервером, на стороне клиента. При следующих запросах эта информация может пересылаться клиентом серверу, который может использовать ее в своих целях. В настоящее время cookie используются практически повсеместно. Типичными задачами, решаемыми при помощи установки cookie являются: автоматическая авторизация пользователя на web-ресурсе, поддержка сессий, и.т.д.

В большинстве случаев cookie устанавливаются сервером и без изменений передаются серверу агентом пользователя при последующих запросах. Однако, доступ к cookie и управление cookie на стороне браузера из клиентских сценариев часто оказывается весьма полезным. Все современные браузеры имеют поддержку доступа к cookie из скриптов. В этой статье мы рассмотрим общие вопросы работы с cookie из сценариев, написанных на JavaScript.

Примечание
Для лучшей передачи смысла, в этой статье я часто буду употреблять записанный по-русски и склоняемый термин cookie. Например, вместо фразы "установить единственную cookie" я могу употребить фразу "установить куку", вместо "определить количество установленных cookie" - "определить количество установленных кук", и.т.д.

Возможно, Вы хорошо знакомы с понятием cookie, возможно - нет, поэтому для начала мы подробно рассмотрим что такое cookie, а затем перейдем непосредственно к рассмотрению работы с cookie из JavaScript.

Что такое cookie

Если говорить кратко, то cookie — это данные, которые могут быть переданы сервером клиенту (во многих случаях в роли клиента выступает браузер) вместе с запрашиваемым multimedia-контентом. Клиент может сохранить эти данные на машине пользователя, и передавать их обратно серверу при следующих запросах (об этом уже говорилось). Поскольку cookie хранятся на машине пользователя (причем, каждый браузер самостоятельно сохраняет полученные им cookie) и могут отдаваться браузером серверу по истечение достаточно большого периода времени (об этом чуть позже), в cookie обычно записывают информацию, так или иначе идентифицирующую пользователя.

Иными словами, cookie можно рассматривать как метки, которые сервер "просит" клиента оставить на машине пользователя. Теперь давайте более подробно разберемся в том, как же "работают" cookie и какие возможности они предоставляют.

Cookie и HTTP

Как уже говорилось, cookie являются составной частью протокола HTTP. От сервера клиенту cookie передаются в заголовке HTTP-ответа сервера. Точнее - в поле Set-Cookie этого заголовка. Поле Set-Cookie может содержать данные нескольких кук. Также в заголовке HTTP-ответа может содержаться несколько полей Set-Cookie. Далее приведен типичный пример одного поля Set-Cookie заголовка HTTP-ответа сервера:

Код
Set-Cookie: PHPSESSID=c867a6ea45268654b2b47469b712a4d0; path=/

Присутствие такого поля в заголовке ответа сервера должно привести к "запоминанию" браузером куки с именем PHPSESSID, значением c867a6ea45268654b2b47469b712a4d0 и атрибутом path, равным "/" (подробнее об атрибуте path см. далее в этой статье).

От клиента серверу cookie передаются в поле COOKIE HTTP-запроса. Допустим, браузер получил с сервера единственную куку в том виде, как было показано выше. Тогда, при следующем обращении к документам с того же сайта, браузер включит в HTTP-запрос строку:

Код
Cookie: PHPSESSID=c867a6ea45268654b2b47469b712a4d0

Это простейший пример передачи cookie от сервера клиенту и обратно.

На самом деле, поле Set-Cookie может включать гораздо больше информации. Формат поля Set-Cookie заголовка HTTP-ответа сервера приведен далее:

Код
Set-Cookie: <name>=<value>[; <name>=<value>]...
    [; expires=<date>][; domain=<domain_name>]
    [; path=<some_path>][; secure][; httponly]

Видно, что строка Set-Cookie заголовка ответа сервера состоит из последовательности подстрок, разделенных символами ";" (точка с запятой). Вначале следуют одна или несколько пар <name>=<value>. Каждая из этих пар соответствует одной куке с именем name и значением value. Потом следуют атрибуты, с которыми устанавливаются куки, содержащиеся в данном поле Set-Cookie. Далее приведено описание значений атрибутов cookie.

  • Атрибут expires. Задается в формате: expires=<date>. Определяет дату и время окончания действия устанавливаемых данным полем Set-Cookie заголовка HTTP-ответа сервера cookie. Значение <date> должно являться строкой, задающей время по гринвичскому меридиану (GMT) в формате "DAY, DD-MMM-YYYY HH:MM:SS GMT" (например "Tue, 28 Feb 2006 12:41:04 GMT"). После истечения срока действия cookie удаляются браузером. Если атрибут expires не задан (время действия cookie не установлено), cookie удаляются при окончании работы браузера. Такие cookie называют "сессионными" (действуют только до окончания текущей сессии).
  • Атрибут domain. Задается в формате domain=<domain_name>. Определяет окончание множества имен доменов, в которых действительны устанавливаемые cookie. К примеру, если при установке cookie, значение <domain_name> равно .codeguru.ru, установленные cookie будут отсылаться серверу при запросе документов с сайтов, расположенных на доменах web.codeguru.ru, forum.codeguru.ru, и.т.д. При этом дополнительным условием отсылки cookie будет являться проверка значения атрибута path — см. далее. Атрибут domain весьма полезен. Он может использоваться, например, для организации единой системы аутентификации пользователя для различных web-сервисов, расположенных на различных поддоменах. Например, на основном сайте и на форуме сайта. Во избежание неконтролируемой отсылки cookie, значение <domain_name> не должно содержать только имя зоны (например, .com, .net.ru, и.т.д.).
  • Атрибут path. Задается в формате path=<some_path>. Определяет множество URL, для которых действительны устанавливаемые cookie. Например, если значение <some_path> при установке cookie равно /temp, то установленные cookie будут отсылаться при запросе документов, включая пути /temp000 и /temp/temp.htm. Если значение path не определено, в качестве него принимается путь к ресурсу, при запросе которого были установлены cookie.
  • Атрибут secure. Это атрибут логического типа. Указание атрибута secure в поле Set-Cookie заголовка HTTP-ответа сервера делает устанавливаемые cookie защищенными. Такие cookie должны отсылаться на сервер только по протоколу https. HTTPS - это, практически, тот же протокол http, только данные между клиентом и сервером передаются через защищенное (данные шифруются) SSL (Secure Socket Layer) соединение.
  • Атрибут HttpOnly. Это атрибут логического типа. Указание атрибута HttpOnly в поле Set-Cookie заголовка HTTP-ответа сервера делает устанавливаемые cookie не доступными клиентским скриптам (это применяется из соображений безопасности).

Атрибуты кук устанавливаются в поле Set-Cookie опционально. Например, при установке защищенной куки с именем ANYCOOKIE, значением ANYVALUE и атрибутом path, равным "/", в заголовке ответа сервера будет присутствовать поле:

Код
Set-Cookie: ANYCOOKIE=ANYVALUE; path=/; secure

Теперь, когда мы разобрались сущностью cookie, перейдем непосредственно к вопросам работы с cookie из скриптов на JavaScript.

Работа с cookie в JavaScript

Далее мы рассмотрим суть механизмов, на которых основан доступ к cookie из скриптов, а затем - основные подходы, которые применяются при работе с cookie.

Cookie в объектной модели документа

Согласно спецификации DOM1, доступ к кукам, сопоставленным некоторому документу, может производиться при помощи манипулирования значением атрибута cookie интерфейса HTMLDocument. В JavaScript данному атрибуту соответствует свойство cookie объекта document (который реализует функциональность, определяемую интерфейсом HTMLDocument).

Примечание
Производители всех современных популярных браузеров декларируют поддержку ими DOM1. Поэтому, доступ к cookie при помощи свойства document.cookie возможен во всех современных браузерах.

Согласно спецификации DOM1, атрибут cookie интерфейса HTMLDocument имеет тип DOMString. То есть, свойство document.cookie должно являться строкой (объектом типа string). И хотя оператор typeof и возвращает значение "string" для объекта document.cookie, семантика работы с этим объектом сильно отличается от семантики работы с обычной строкой в JavaScript.

Объект document.cookie в деталях

Итак, давайте детально изучим объект document.cookie, его поведение и принципы его использования для манипулирования cookie. Для этого последовательно рассмотрим операции, которые могут быть произведены с cookie посредством этого объекта: установка, получение, модификация, удаление cookie.

Установка cookie скриптом осуществляется путем присваивания объекту document.cookie строки, формат которой фактически идентичен формату поля Set-Cookie заголовка HTTP-ответа сервера (мы рассматривали это ранее). При этом стоит отметить, что использовать атрибут HttpOnly при установке cookie скриптом бессмысленно (ведь атрибут HttpOnly указывает на недоступность устанавливаемой cookie для скрипта). Далее приведен код простого примера установки cookie:

Код
document.cookie = "test=test_value; expires=Wed, 1 Mar 2006 00:00:00";

В данном примере устанавливается одна кука с именем test, значением test_value и временем истечения срока действия 1 марта 2006 года в 0 часов, 0 минут, 0 секунд. Данная операция устанавливает одну куку. Как же установить две или более куки, и еще с разными атрибутами ? Все достаточно просто. Надо произвести несколько таких операций присваивания:

Код
document.cookie = "test=test_value; expires=Wed, 1 Mar 2006 00:00:00";
document.cookie = "test1=test_value1; path=/; secure";

В этом примере устанавливаются две куки с различным набором атрибутов. В этом и состоит отличие объекта document.cookie от обычного объекта-строки. При присваивании ему строковых значений, описывающих различные куки, происходит "запоминание", "накапливание" кук. То есть, значение (если это так можно назвать) объекта document.cookie не перезаписывается, а накапливается.

Примечание
Кроме того, модификация и удаление установленных cookie также производится посредством операции присваивания значений объекту document.cookie (см. далее в этой статье).

Получение установленных cookie сводится к получению значения объекта document.cookie. Это значение является строкой, содержащей последовательность разделенных символами "; " пар вида <имя>=<значение> всех установленных для документа cookie. Например:

Код
cookie1=10; user_name=Ivan; var=00

Обратите внимание, что в одной строке возвращаются имена и значения всех кук. Кроме того, cookie возвращаются без атрибутов. То есть после установки куки мы не сможем получить значения атрибутов, с которыми ее устанавливали.

Модификация значения или атрибутов (например, времени окончания срока действия) уже установленной куки может быть произведена установкой куки с тем же именем, но новым значением и/или атрибутами.

Удаление отдельной куки производится путем установки ее значения (присваиванию соответствующей строки объекту document.cookie) с указанием времени истечения срока действия куки ранее текущего момента времени (время на машине пользователя).

Примечание
Физически, удаленные куки будут удалены (из места хранения кук браузером - обычно это файлы на диске), скорее всего, только при закрытии браузера.

Для иллюстрирования всего сказанного ранее, рассмотрим небольшой, но весьма наглядный пример. Код примера приведен далее:

Код
document.cookie = "cookie_1=val_1"; // установка cookie_1
document.writeln(document.cookie);
document.cookie = "cookie_2=val_2"; // установка cookie_2
document.writeln(document.cookie);
document.cookie = "cookie_2=val_2_modified"; // модификация cookie_2
document.writeln(document.cookie);

// удаление cookie_2
var oDate = new Date();
oDate.setFullYear(oDate.getFullYear() - 1);
document.cookie = "cookie_2=; expires=" + oDate.toGMTString();
document.writeln(document.cookie);

Как видно из кода, в примере сначала производится установка cookie с именами cookie_1 и cookie_2, затем значение cookie_2 модифицируется, а затем кука с именем cookie_2 удаляется. Для удаления куки cookie_2 для присваивания значения объекту document.cookie генерируется строка включающая атрибут expires. Значение атрибута expires формируется путем вызова метода toGMTString объекта oDate типа Date. Объект создается при помощи вызова конструктора Date без параметров (при этом созданный объект сохраняет значение времени на момент его создания). Для получения значения времени, соответствующего моменту в прошлом (отстоящему от текущего на один год), вызывается метод setFullYear объекта oDate. Ему передается уменьшенное на единицу значение года времени, сохраненного в oDate.

После совершения каждого действия с cookie, скрипт генерирует вывод при помощи метода document.writeln. Листинг вывода, сгенерированного скриптом, приведен далее:

Код
cookie_1=val_1
cookie_1=val_1; cookie_2=val_2
cookie_1=val_1; cookie_2=val_2_modified
cookie_1=val_1

Как видите, манипулирование cookie посредством объекта document.cookie осуществляется достаточно просто. Однако, существуют и неочевидные моменты работы с cookie, которые мы рассмотрим в следующем разделе.

Общие принципы работы с cookie в JavaScript

Теперь давайте обсудим общие принципы и подходы, используемые при работе с cookie в JavaScript. Необходимость применения этих подходов вытекает из специфики самих cookie и семантики работы объекта document.cookie. Выделим основные особенности:

  • Как уже было сказано, document.cookie не является обычной строкой. Данный объект реализует интерфейс доступа к cookie, используя семантику работы с объектом-строкой. Строка, возвращаемая при получении значения данного объекта-свойства имена и значения всех cookie, сопоставленных документу. Это означает, что для получения значения произвольной cookie по ее имени, необходимо производить разбор этой строки.
  • При установке cookie, символами, разделяющими пары <имя>=<значение>, а также атрибуты устанавливаемых кук, являются "; " (точка с запятой и пробел), поэтому эти символы нельзя использовать в значениях cookie. Кроме того, в значениях cookie и атрибутов недопустимо применять символы табуляции, возврата каретки, перевода строки и другие специальные символы. Поэтому, если н качестве значения cookie необходимо записать произвольную информацию, эту информацию необходимо каким либо образом закодировать, чтобы исключить из строки недопустимые символы.
  • Хотя управление cookiе посредством объекта document.cookie предоставляется всеми современными браузерами, доступ к cookie возможен не всегда. Пользователь может запретить модификацию cookie скриптами в настройках браузера. Поэтому в скриптах, производящих некоторые действия с куками, необходимо осуществлять проверку поддержки кук браузером.

Итак, разберем отдельно каждый пункт.

Пункт первый. Для получения значения произвольной cookie по ее имени, необходимо производить разбор строки, полученной как значение объекта document.cookie. В принципе, поскольку набор символов-разделителей в этой строке фиксирован (обычно пары <имя>=<значение> разделяются последовательностью "; "), разбор строки не представляет из себя какой либо сложности. Можно осуществить последовательный поиск в цикле необходимой пары <имя>=<значение>, а затем выделить нужное значение из полученной подстроки. Можно использовать для разбора строки регулярное выражение.

Для разрешения проблемы, описанной во втором пункте - возможности наличия в строке значения устанавливаемой куки недопустимых символов, можно использовать кодирование строки значения куки в виде escape-последовательности. Для этого в JavaScript надо использовать функцию escape.

И, наконец, для определения поддержки браузером cookie (пункт 3) можно использовать свойство cookieEnabled объекта navigator, установку/чтение "тестовой" куки, либо комбинацию этих способов (что гораздо предпочтительнее).

Примечание
Реализацию основных механизмов работы с cookie в JavaScript вы можете найти в исходном коде библиотеки функций, описанной в статье "Библиотека функций для работы с cookie в JavaScript", а пример реального использования cookie в клиентском сценарии описан в статье "Сохранение информации о пользователе в cookie".

На этом все.


WEBITEX
Rambler's Top100
Тел.: +7 (495) 749 43 55
E-mail: info@webitex.ru