Xiper

Cookies — установка

Автор: Андрей Косяк Дата публикации:

В первой статье Cookies — печем печеньки мы смотрели на куки с дальней дистанции, поэтому если ты разобрался в общих понятиях и назначении cookies — можно приступать непосредственно к выпечке (вот и духовочку я раздобыл), поэтому, надеваем кулинарный колпак и подходим поближе. Будем выпекать!

Арт. подготовка

Ты уже знаешь, что куки — строка, а также, знаешь, как выглядит кука глазами браузера. При установке в браузер, кука имеет вид все той же строки:

"cookieName=cookieValue; expires=Fri, 21 Jan 06:10:00 GMT; path=/; domain=lessons.xiper; secure=true;"

Условия существования куки оговариваются пятью параметрами (парами ключ=значение) (ВАЖНО! После каждого должен стоять символ-разделитель ";"), рассмотрим их:

Начинка куки

"cookieName=cookieValue;" — основной параметр куки, без него кука теряет свой смысл. Здесь cookieName — уникальное имя для куки, а cookieValue — информация (значение), которую она будет хранить. Забегая немного вперед, скажу, что в качестве значения может быть что угодно, любая, удобная тебе, структура хранимых данных (да хоть JSON), а также какие угодно символы. Единственная пара, которая является обязательной при установке куки.

Время жизни

"expires=Fri, 21 Jan 06:10:00 GMT" — эта пара хоть и необязательна, но играет очень важную роль, наряду с первой. Этот параметр определяет время жизни куки, а именно, с точностью до секунды, в указанную дату, кука «прикажет долго жить». Если этот параметр не указать, то кука будет действительна только в течение сессии, а это значит, что при закрытии браузера она будет удалена.

Важным моментом является формат даты. Дата должна быть задана ТОЛЬКО в текстовом формате (Fri, 21 Jan 06:10:00 GMT). Снова, забегая немного вперед, скажу, что в этом нам поможет объект Date, в нем есть все необходимые инструменты.

Путь установки

"path=/" — этим параметром задается путь (каталог), для которого действительна кука. Сейчас path имеет значение "/", это ничто иное, как корневой каталог, поэтому кука будет доступна для чтения абсолютно всем каталогам сайта. В случае если доступ к куке должен быть ограничен, то параметр path просто не указываем или указываем в нем общий родительский каталог, и кука будет установлена для конкретного каталога, но специфика такова, что кука будет доступна всем его подкаталогам, в то же время — не видна смежным и родительским каталогам.

Для чего это? Представим элементарную ситуацию: интернет-кафе, сначала пришел пользователь Вася, поработал со своей страницей в соцсети, а после него пришел Петя и, на том же компьютере, в той же сети, поработал со своей страницей. Страницы участников находятся в одном домене, но лежат, как правило, в смежных каталогах. К примеру: страница Васи — Можно представить, какой будет хаос, если куки будут устанавливаться в корневой каталог: Вася сможет оперировать куками Пети и наоборот. Я думаю ни одному, ни другому такой вариант не понравится. Поэтому, в данном случае, будет уместно, если куки будут привязаны только к каталогу конкретного пользователя, следовательно, ко всем его подкаталогам.

Домен

"domain=lessons.xiper" — эта пара определяет домен, в котором действительны куки. Как правило, явно использовать приходится редко. Ситуация с этим параметром похожа на ситуацию с параметром path, с той разницей, что в Domain мы оперируем доменами и сабдоменами а не каталогами. Т.е., в данном случае, куки установленные для сабдомена lessons.xiper не будут доступны для tricks.xiper. Чтоб исправить это, нужно указать общий для них домен — xiper. Если параметр не указан, то по умолчанию используется доменный адрес документа.

Безопасность

"secure=true" — параметр безопасности. Если этот параметр установлен в true, браузер отправит куки только тому серверу, который запросит их по безопасному каналу (SSL). Этот параметр также используется редко. По умолчанию принимает значение false.

Первый блин комом?

Вот теперь попробуем угостить наш браузер печенюшкой. В этом нам поможет объект document.cookie:

document.cookie = 'firstCookie=Первый блин комом?; expires=Fri, 21 Jan 06:10:00 GMT; path=/;';

Результат можно увидеть, открыв в своем браузере раздел куки или же банально:

document.cookie = 'firstCookie=Первый блин комом?; expires=Fri, 21 Jan 06:10:00 GMT; path=/;';
alert(document.cookie);

И совсем и не комом! Все гуд, кука на месте.

Заметка

Обращаю внимание на особенность браузеров на WebKit. Они отказываются ставить куки, если документ открыт локально. Я, обычно, в таких случаях пользуюсь локальным сервером, так же он понадобится при работе с AJAX. Поэтому, как говорится, маст хэв! К примеру, Denwer (ссылка в конце статьи).

Больше cookies

C одной кукой разобрались. А как быть, если нужно хранить, к примеру, данные из формы (логин, e-mail, номер телефона и т.п.)? В таком случае можно поступить так:

document.cookie = 'myLogin=Мой логин; expires=Fri, 21 Jan 06:10:00 GMT; path=/;';
document.cookie = 'myEmail=my@email.com; expires=Fri, 21 Jan 06:10:00 GMT; path=/;';
document.cookie = 'myPhone=1234567; expires=Fri, 21 Jan 06:10:00 GMT; path=/;';

Таким образом, имеем три куки, которые хранят соответственно логин, электронный ящик и номер телефона. Но ты же помнишь, об ограничениях на количество куков от одного домена, впрочем, как и их общего количества? Значит, таким способом мы можем хранить только ограниченное количество значений для полей. А если такое ограничение "связывает" нам руки, мы можем поступить так:

var    formData = escape('Мой логин;my@email.com;1234567');
       document.cookie = 'myFormCookie='+formData+'; expires=Fri, 21 Jan 06:10:00 GMT; path=/;';

В итоге имеем 1 используемое место под куку. Все данные я "склеил" в одну переменную и разделил их символом ";", впрочем, в качестве разделителя внутри переменной можно использовать любой символ, это уже наша инициатива, здесь только нужно позаботиться о том, чтоб этот разделитель не встречался в значениях полей, иначе возникнут трудности в дальнейшем, когда нужно будет их прочесть. В таком случае, конечно же, нужно еще помнить об ограничении на размер куки (4кб).

Зачем функция escape? Все довольно просто, она кодирует значение куки в 16-ричное представление. Для чего? Во-первых, браузер отправляет куки серверу, а для того, чтоб данные одинаково могли быть прочтены на серверах под любыми системами, используется данная кодировка. Во-вторых, если мы, используя разделитель ";" в переменной со значениями полей, не закодируем эту строку, то кука, по меньшей мере, просто не правильно установится, ведь разделитель ";" используется для отделения параметров самой куки. Этот момент нужно взять на вооружение и, впредь, использовать по-умолчанию при передаче информации (cookie, AJAX).

"…и время ни на миг не остановишь"

Теперь разберемся с параметром expires. Неудобство в том, что до этого момента мы прописывали время жизни для куки вручную. Но, в реальных условиях, такой подход практически не применим. Как минимум, потому, что при каждом очередном заходе на сайт, время жизни куков должно продлеваться на какой-то фиксированный строк, что, вобщем-то, оправдано и логично. Поэтому в данном вопросе нам полностью поможет объект Date:

var    formData = escape('Мой логин;my@email.com;1234567');
       cookieExp = new Date();                       // создаем объект Date
       cookieExp.setMonth(cookieExp.getMonth()+1);   // устанавливаем текущий месяц и к нему добавляем еще один
       document.cookie = 'myFormCookie='+formData+'; expires='+cookieExp.toGMTString()+'; path=/;';

Такими действиями мы установили время жизни куки ровно в 1 месяц. Подробно на объекте Date в этой статье оснавливаться не буду, лишь опишу схему установки срока:

  • строка 2: объявляем cookieExp как объект Date. Теперь cookieExp содержит текущую дату;
  • строка 3: переустановка в cookieExp месяца. При помощи метода getMonth извлекаем текущий месяц и прибавляем к нему еще один. В итоге в cookieExp запишется следующий месяц;
  • строка 6: в этой строке используем метод toGMTString(), для перевода даты в текстовый формат;

Таким образом, в зависимости от того, какое время жизни для куки нужно установить, можно использовать и другие методы объекта Date: от get/setMilliseconds() до get/setFullYear() (от получения/установки миллисекунд до получения/установки года).

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

Вывод

Как видишь, установка куков не есть чем-то сверхъестественным, нужно только помнить (какой раз уже повторяюсь :) ) об ограничениях и все будет типи-тип, ну, или топи-топ. Следующий материал будет о том, как наши печеньки достать из духовочки. Вот там придется немного поразмышлять.

Куда дальше

Полезности

  • Denwer — Джентльменский Набор Web-Разработчика (PHP 5.3.3, MySQL 5.1, PostgreSQL 8.4 etc.)