Все ленты — последние статьи

Работа с Cookies на PHP

Введение:

Откуда возник термин «cookie» никто достоверно не знает, хотя считается, что во времена зарождения Unix-систем где-то использовалось словосочетание Magic Cookies. Имелись в виду «квитанции» (token, ticket), которыми обменивались программы.

Cookie является решением одной из наследственных проблем HTTP протокола (HyperText Transfer Protocol). Эта проблема заключается в непостоянстве соединения между клиентом и сервером, как при FTP или Telnet сессии, т.е. для каждого документа (или файла) при передаче по HTTP протоколу посылается отдельный запрос. Включение cookie в HTTP протокол дало частичное решение этой проблемы. Иначе говоря, транзакция завершается после того, как браузер сделал запрос, а сервер выдал соответствующий ответ. Сразу после этого сервер «забывает» о пользователе и каждый следующий запрос того же пользователя считает новым пользователем.

 

Используя cookie, можно эмулировать сессию по HTTP протоколу. Коротко принцип эмуляции сессии таков: на первом запросе выдается соотвествующее значение cookie, а при каждом последующем запросе это значение читается из переменной окружения HTTP_COOKIE и соответствующим образом обрабатывается.

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

Итак,приступим к практике:
1. Задание cookie с помощью PHP

Для задания этой финкции в языке php есть оператор:
setcookie() . Самое приятное, что функция setcookie() воспринимает до шести аргументов, в зависимости от того, как вы собираетесь управлять значениями cookie и кто будет считывать ее значения.

Простейший способ установить cookie таков:

setcookie('name', 'bret');

Затем, для каждой последующей страницы на Вашем сайте, просматриваемой в течение данной сессии (пока пользователь не покинет сайт) переменная $name будет иметь значение 'bret' и его можно легко прочитать средствами PHP. Этот тип cookie известен как cookie-сессия, поскольку значение сохраняется в течение пользовательской сессии.

Если Вы хотите, чтобы значение cookie запоминалось браузером после того, как пользователь закончит сессию, Вы должны передать функции setcookie() третий параметр — дату истечения срока действия cookie. Поскольку PHP сформировался в основном в среде Unix, Вы должны представить время истечения срока действия cookie как число секунд, прошедших с 1 января 1970 г. Если Вы имеете опыт программирования для Unix, это не покажется Вам удивительным. Но, если Вы программировали только в среде Windows или Macintosh, Вы, может быть, удивитесь, что за чокнутый народ эти Unix-оиды.

Но не бойтесь. PHP имеет очень удобную функцию, mktime() . Вы указываете ей в качестве параметров (в указанном порядке) час, минуту, секунду, месяц, день и год, задающие тот момент времени, который Вы хотите представить в воспринимаемом UNIX формате, и mktime() возвращает Вам число секунд, прошедших с 1 января 1970 г. до указанного момента времени. Например, если Вы хотите, чтобы срок действия cookie истек 1 января 2000 г., Вы записываете:

<?php
$y2k = mktime(0,0,0,1,1,2000);
setcookie('name', 'bret', $y2k);
?>

Если Вы хотите изменить значение cookie на новое, Вы можете просто переписать его (её?) значение. Таким образом, даже если браузер уже посылал значение cookie серверу на одной из предыдущих страниц, вполне возможно сообщить серверу, что в действительности Вас зовут «jeff.»

<?php
$y2k = mktime(0,0,0,1,1,2000);
setcookie('name', 'jeff', $y2k);
?>

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

<?php
$name = 'jeff';
$y2k = mktime(0,0,0,1,1,2000);
setcookie('name', $name, $y2k);
?>

Следующие два параметра функции setcookie() позволяют Вам задать путь и имя домена того, кто может прочитать значение Вашего cookie. По умолчанию только страницы, расположенные в том же каталоге или ниже в структуре подкаталогов того сервера, который установил cookie, могут прочитать его (её??) значение. Это делается из соображений безопасности. Однако, если у Вашего сервера два доменных имени: «www.domain.com» и «other.domain.com», и Ваш экаунт позволяет Вам обслуживать страницы из каталога ~/myhome, Вы должны вызывать функцию setcookie() следующим образом:

setcookie('name', 'jeff', $y2k, '~/myhome', '.domain.com');

Последний параметр функции setcookie() , который мы никогда не использовали, требует, чтобы значение cookie передавалось только на те Web-сервера, которые испольуют безопасный протокол соединения, такой как SSL. Если Вам это нужно, то задайте для шестого параметра значение 1.

Удалить cookie тоже очень просто, достаточно передать функции setcookie() имя cookie и PHP сделает все остальное:

setcookie('name');

В заключение нужно сделать еще одно замечание, касающееся использования cookie. В силу того, как организована обработка cookies в протоколе HTTP, необходимо установить значения всех cookie до вывода какого-либо текста. Если сделать наоборот, PHP выдаст Вам предупреждение и значение cookie не будет послано. Вот так правильно:

<?php
setcookie('name', 'jeff');
echo "Hello Everyone!";
?>

А так — нет:

<?php
echo "Hello Everyone!";
setcookie('name', 'jeff');
?>

2. Задание cookie с помощью JavaScript

Можно задавать значение cookie, используя язык JavaScript. Единственный недостаток этого способа заключается в том, что не все браузеры его поддерживают. Ниже приведены примеры функций JavaScript, написанные Алексеем Александровым для скрипта «Органайзер».

Пример. Функция установки значения cookie

// name — имя cookie
// value — значение cookie
// [expires] — дата окончания действия cookie (по умолчанию — до конца сессии)
// [path] — путь, для которого cookie действительно (по умолчанию — документ, в котором значение было установлено)
// [domain] — домен, для которого cookie действительно (по умолчанию — домен, в котором значение было установлено)
// [secure] — логическое значение, показывающее требуется ли защищенная передача значения cookie

function setCookie(name, value, expires, path, domain, secure) {
var curCookie = name + "=" + escape(value) +
((expires) ? "; expires=" + expires.toGMTString() : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "")
if (!caution (name + "=" + escape(value)).length <= 4000)
document.cookie = curCookie
else
if (confirm("Cookie превышает 4KB и будет вырезан !"))
document.cookie = curCookie
}

Пример. Функция чтения значения cookie

Возвращает установленное значение или пустую строку, если cookie не существует.

// name — имя считываемого cookie

function getCookie(name) {
var prefix = name + "="
var cookieStartIndex = document.cookie.indexOf(prefix)
if (cookieStartIndex == -1)
return null
var cookieEndIndex = document.cookie.indexOf(";", cookieStartIndex + prefix.length)
if (cookieEndIndex == -1)
cookieEndIndex = document.cookie.length
return unescape(document.cookie.substring(cookieStartIndex + prefix.length, cookieEndIndex))
}

Пример. Функция удаления значения cookie

Принцип работы этой функции заключается в том, что cookie устанавливается с заведомо устаревшим параметром expires, в данном случае 1 января 1970 года.

// name — имя cookie
// [path] — путь, для которого cookie действительно
// [domain] — домен, для которого cookie действительно
function deleteCookie(name, path, domain) {
if (getCookie(name)) {
document.cookie = name + "=" +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
"; expires=Thu, 01-Jan-70 00:00:01 GMT"
}

3. Задание cookie с помощью Perl

Самый мощный и гибкий способ управления документами с использованием механизма cookie — с помощью CGI-скриптов. Задание значения cookie на Perl будет выглядеть следующим образом:

print "Content-type: text/htmln";
print "Set-Cookie: username=aaa13; expires=Friday, 31-Dec-99 23:59:59 GMT; path=/; domain=www.citforum.ru;nn";

Скрипт при выдаче результатов работы генерирует HTTP заголовок:

Content-type: text/html
Set-Cookie: «username=aaa13; expires=Friday, 31-Dec-99 23:59:59 GMT; path=/; domain=www.webscript.ru;»

Чтобы прочитать в скрипте ранее заданное значение cookie, используется переменная окружения HTTP_COOKIE.

$cookie = $ENV{'HTTP_COOKIE'};

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

А теперь о грусном…
Ограничения:

Клиент (браузер) имеет следующие ограничения для cookies:

всего может храниться до 300 значений cookies
каждый cookie не может превышать 4Кбайт
с одного сервера или домена может храниться до 20 значений cookie

Если ограничение 300 или 20 превышается, то удаляется первая по времени запись. При превышении лимита объема в 4Кбайт корректность значения cookie страдает — отрезается кусок записи (с начала этой записи) равный превышению объема.

В случае кэширования документов, например, proxy-сервером, поле Set-cookie HTTP заголовка никогда не кэшируется.

Если proxy-сервер принимает ответ, содержащий поле Set-cookie в заголовке, предполагается, что поле доходит до клиента вне зависимости от кода возврата 304 (Not Modified) или 200 (OK). Соответственно, если клиентский запрос содержит в заголовке Cookie, то он должен дойти до сервера, даже если жестко установлен параметр If-modified-since.

Вот и все, удачи!