ГЛАВА 13. Cookie и отслеживание сеанса
Отслеживание сеанса
Сеансом(session) называется период времени, который начинается с момента прихода пользователя на сайт и завершается, когда пользователь покидает сайт. В течение сеанса часто возникает необходимость в сохранении различных переменных, которые бы «сопровождали» пользователя при перемещениях на сайте, чтобы вам не приходилось вручную кодировать многочисленные скрытые поля или переменные, присоединяемые к URL.
Рассмотрим следующую ситуацию. При входе на сайт пользователю присваивается уникальный идентификатор сеанса(SID), который сохраняется на компьютере пользователя в cookie с именем PHPSESSJD. Если использование cookie запрещено или cookie вообще не поддерживаются, SID автоматически присоединяется ко всем локальным URL на протяжении сеанса. В то же время на сервере сохраняется файл, имя которого совпадает с SID. По мере того как пользователь перемещается по сайту, значения некоторых параметров должны сохраняться в виде сеансовых переменных. Эти переменные сохраняются в файле пользователя. При последующем обращении к сеансовой переменной сервер открывает сеансовый файл пользователя и ищет в нем нужную переменную. В сущности, в этом и заключается суть отслеживания сеанса. Конечно, информация с таким же успехом может храниться в базе данных или в другом файле.
Интересно? Еще бы. После всего сказанного вы, несомненно, лучше поймете различные проблемы конфигурации, рассматриваемые ниже. Особенно важную роль играют три флага. Первый флаг, --enable-trans-id, включается в процесс конфигурации в том случае, если вы собираетесь использовать SID(см. ниже). Два других флага, track_vars и register_globals, включаются и отключаются по мере необходимости в файле php.ini. Последствия активизации этих флагов рассматриваются ниже.
--enable-trans-id
Если РНР компилируется с этим флагом, ко всем относительным URL автоматически присоединяется идентификатор сеанса(SID). Дополнение записывается в формате имя_сеанса=идентификатор_сеанса, где имя_сеанса определяется в файле php.ini(см. ниже). Если вы не захотите включать этот флаг, в качестве SID можно использовать константу.
track_vars
Установка флага track_vars позволяет использовать массивы $HTTP_*_VARS[], где * заменяется одним из значений EGPCS(Environment, Get, Post, Cookie, Server). Данный флаг необходим для того, чтобы значения SID передавались с одной страницы на другую. В РНР 4.03 этот флаг всегда находится в установленном состоянии.
register_globals
В результате установки этого флага все переменные EGPCS становятся доступными глобально. Если вы не хотите, чтобы массив глобальных переменных заполнялся данными, которые вам, возможно, и не понадобятся, флаг следует сбросить.
Если флаг register_globals сброшен, а флаг track_vars установлен, ко всем переменным GPC можно обращаться через массив $HTTP_*_VARS[]. Например, если сбросить флаг register_globals, к стандартной переменной $PHP_SELF придется обращаться в виде $HTTP_SERVER_VARS["PHP_SELF"].
Существует целый ряд других аспектов конфигурации, о которых следует позаботиться. Эти директивы перечислены в табл. 13.1 с указанием стандартных значений, задаваемых по умолчанию в файле php.ini. Перечисление производится в порядке появления директив в файле.
Таблица 13.1. Сеансовые директивы в файле php.ini
Директива |
Описание |
session.save_handler = files |
Определяет способ хранения сеансовых данных на сервере. Возможны три варианта: в файле(files), в общей памяти(mm) или с использованием функций, определяемых пользователем(User). Последний вариант позволяет легко сохранить информацию в любом формате — например, в базе данных |
session.save_path =/tmp |
Определяет каталог для сеансовых файлов РНР. На платформе Linux обычно используется значение по умолчанию('/tmp'). На платформе Windows следует указать путь к какому-нибудь каталогу, в противном случае произойдет ошибка |
session_use_cookies =1 |
При установке этого флага для сохранения идентификатора сеанса на компьютере пользователя используются cookie |
session.name =PHPRESSID. |
Если флаг session.use_cookies установлен, то значение session.name используется в качестве имени cookie. Имя может состоять только из алфавитно-цифровых символов |
session.auto_start = 0 |
При установке флага session.auto_start сеанс автоматически инициируется при первоначальном запросе со стороны клиента |
session.cookie_lifetime = 0 |
Если флаг session.use_cookies установлен, то значение session.cookie_lifetime определяет срок действия отправляемых cookie. Если параметр равен 0, то все cookie становятся недействительными при завершении сеанса |
session.cookie_path = / |
Если флаг session.use_cookies установлен, то значение session.cookie_path определяет каталог, для которого отправляемые cookie считаются действительными |
session.cookie_domain = |
Если флаг session.use_cookies установлен, то значение session.cookie_domain определяет домен, для которого отправляемые cookie считаются действительными |
session.serialize_handler = php |
Имя обработчика, используемого в процессе сериализации данных. В настоящее время определены два возможных значения: php и WDDX |
session.gc_probability =1 |
Вероятность активизации сборщика мусора РНР(в процентах) |
session.gc_maxlifetime=1440 |
Промежуток времени(в секундах), по истечении которого данные сеанса считаются недействительными и уничтожаются. Отсчет начинается с момента последнего обращения пользователя в текущем сеансе |
session.referer_check = |
Если этому параметру присвоено строковое значение, каждый запрос к странице при включенном отслеживании сеанса начинается с проверки того, что заданная строка присутствует в глобальной переменной $HTTP_REFERER. Если строка не найдена, идентификаторы сеансов игнорируются |
session.enthropy_fiie = |
Ссылка на внешний файл с дополнительной случайной информацией, используемой при генерации идентификаторов сеансов. В системах UNIX для этой цели обычно используются два устройства, /dev/random и /dev/urandom. Устройство /dev/random получает случайные данные от ядра, а устройство /dev/urandom генерирует случайную строку при помощи хэш-алгоритма М05. Короче говоря, /dev/random работает быстрее, a /dev/urandom генерирует «более случайные» строки |
session.enthropy_length = 0 |
Если флаг session.enthropy_file установлен, то session.enthropyjength определяет количество байт, читаемых из файла session.enthropy_file |
session.cache limiter = nocache |
Способ управления кэшем для страниц сеанса. В настоящее время определены три возможных значения: nocache, public и private |
session.cache_expire =180 |
Продолжительность жизни кэшированных страниц сеанса(в минутах) |
После внесения всех необходимых изменений в настройку сервера мы переходим к непосредственной реализации отслеживания сеанса на вашем сайте. Благодаря нескольким стандартным функциям РНР этот процесс не так уж сложен. Первое, что необходимо знать, — сеанс инициируется функцией session_start(). Конечно, при включении директивы session.auto_start в файл php.ini(см. выше) необходимость в вызове этой функции отпадает. Тем не менее, в оставшейся части этого раздела я буду использовать эту функцию, чтобы примеры выглядели более последовательно. Функция session_start() имеет простой синтаксис, поскольку она не получает параметров и возвращает логическую величину.
Директива session.save_handler настолько важна, что я счел необходимым посвятить ей отдельный раздел. Он находится в конце главы под заголовком «Назначение пользовательских функций для хранения сеансовых данных».
session_start()
Функция session_start() имеет двойное назначение. Сначала она проверяет, начал ли пользователь новый сеанс, и если нет — начинает его. Синтаксис функции
session_start(): boolean session_start()
Если функция начинает новый сеанс, она выполняет три операции: назначение пользователю SID, отправку cookie(если в файле php.ini установлен флаг session_cookies) и создание файла сеанса на сервере. Второе назначение функции заключается в том, что она информирует ядро РНР о возможности использования в сценарии, в котором она была вызвана, сеансовых переменных.
Сеанс начинается простым вызовом session_start() следующего вида:
session_start():
Если сеанс можно создать, значит, его можно и уничтожить. Это делается функцией session_destroy().
Функция session_start() возвращает TRUE независимо от результата. Следовательно, проверять ее в условиях if или в команде die() бессмысленно.
session_destroy()
Функция session_destroy() уничтожает все хранимые данные, относящиеся к сеансу текущего пользователя. Синтаксис функции session_destroy():
boolean session_destroy()
Следует помнить, что эта функция не уничтожает cookie на браузере пользователя. Впрочем, если вы не собираетесь использовать cookie после конца сеанса, просто присвойте параметру session.cookie_lifetime в файле php.ini значение()(используемое по умолчанию). Пример использования функции:
<?
session_start();
// Выполнить некоторые действия для текущего сеанса
session_destroy();
?>
Теперь вы умеете уничтожать сеансы, и мы можем перейти к работе с сеансовыми переменными. Возможно, самой важной сеансовой переменной является SID(идентификатор сеанса). Его легко можно получить при помощи функции session_id().
session_id()
Функция session_id() возвращает SID для сеанса, созданного функцией session_start(). Синтаксис функции session_id():
string session_id([string sfd])
Если в необязательном параметре передается идентификатор, то значение SID текущего сеанса изменяется. Однако следует учитывать, что cookie при этом заново не пересылаются. Пример:
<?
session_start()
print "Your session identification number is ".sessionjd():
session_destroy():
?>
Результат, выводимый в браузере, выглядит примерно так:
Your session identification number is
067d992a949114ee9832flcllcafc640
Как же создать свою сеансовую переменную? С помощью функции session_register().
session_register()
Функция session_register() регистрирует имена одной или нескольких переменных для текущего сеанса. Синтаксис функции session_register():
boolean session_register(mixed имя_переменной1 [, mixed имя_переменной2... ])
Следует помнить, что вы регистрируете не сами переменные, а их имена. Если сеанс не существует, функция session_register() также неявно вызывает session_start() для создания нового сеанса.
Прежде чем приводить примеры использования session_register(), я хочу представить еще одну функцию, связанную с отслеживанием сеанса, — session_is_registered(). Эта функция проверяет, была ли зарегистрирована переменная с заданным именем.
session_is_registered()
Часто требуется определить, была ли ранее зарегистрирована переменная с заданным именем. Задача решается при помощи функции session_is_registered(), имеющей следующий синтаксис:
boolean session_is_registered(string имя_переменной)
Применение функций session_register() и session_is_registered() будет продемонстрировано на классическом примере использования сеансовых переменных — счетчике посещений(листинг 13.5).
Листинг 13.5. Счетчик посещений сайта пользователем
<?
session_start();
if(! sessionjs_registered('hits')) :
session_register( 'hits' ) ;
endif ;
$hits++;
print "You've seen this page $hits times.
?>
Сеансовые переменные можно не только создавать, но и уничтожать. Для этой цели применяется функция session_unregister().
session_unregister()
Сеансовые переменные уничтожаются функцией session_unregister(). Синтаксис:
boolean session_unregister(string имя_переменной')
При вызове функции передается имя сеансовой переменной, которую вы хотите уничтожить.
<?
session_start();
session_register('username');
// Использовать переменную $username.
// Когда переменная становится ненужной - уничтожить ее.
session_unregister('username');
session_destroy();
?>
Как и в случае с функцией session_register, помните, что в параметре указывается не сама переменная(то есть имя с префиксом $). Вместо этого указывается имя переменной.
session_encode()
Функция session_encode() обеспечивает чрезвычайно удобную возможность форматирования сеансовых переменных для хранения(например, в базе данных). Синтаксис функции session_encode():
boolean session_encode()
В результате выполнения этой функции все сеансовые данные форматируются в одну длинную строку, которую можно сохранить в базе данных.
Пример использования session_encode() приведен в листинге 13.6. Предположим, что на компьютере «зарегистрированного» пользователя имеется cookie, в котором хранится уникальный идентификатор этого пользователя. Когда пользователь запрашивает страницу, содержащую листинг 13.6, UID читается из cookie и присваивается идентификатору сеанса. Мы создаем несколько сеансовых переменных и присваиваем им значения, после чего форматируем всю информацию функцией session_encode() и заносим в базу данных MySQL.
Листинг 13.6. Использование функции session_encode() для сохранения данных в базе данных MySQL
<?
// Инициировать сеанс и создать сеансовые переменные
session_register('bgcolor');
session_register('fontcolor');
// Предполагается, что переменная $usr_id(с уникальным
// идентификатором пользователя) хранится в cookie
// на компьютере пользователя.
// При помощи функции session_id() присвоить идентификатору
// сеанса уникальный идентификатор пользователя(UID),
// хранящийся в cookie.
$id = session_id($usr_id);
// Значения следующих переменных могут задаваться пользователем
// на форме HTML
$bgcolor = "white";
$fontcolor = "blue";
// Преобразовать все сеансовые данные в одну строку
$usr_data = session_encode();
// Подключиться к серверу MySQL и выбрать базу данных users
@mysql_pconnect("localhost", "web", "4tf9zzzf")
or die("Could not connect to MySQL server!");
@mysql_select_db("users") or die("Could not select user database!");
// Обновить пользовательские параметры страницы
$query = "UPDATE user_info set page_data='$usr_data' WHERE user_id='$id'";
$result - mysql_query($query) or die("Could not update user information!");
?>
Как видите, быстрое преобразование всех сеансовых переменных в одну строку избавляет нас от необходимости создавать несколько полей для хранения/загрузки данных, а также несколько уменьшает объем программы.
session_decode()
Все сеансовые данные, ранее преобразованные в строку функцией sessi on_encode(), восстанавливаются функцией session_decode(). Синтаксис:
string session_decode(string сеансовые_данные)
В параметре сеансовые_данные передается преобразованная строка сеансовых переменных, возможно — прочитанная из файла или загруженная из базы данных. Строка восстанавливается, и все сеансовые переменные в строке преобразуются к исходному формату.
В листинге 13.7 продемонстрировано восстановление закодированных сеансовых переменных функцией session_decode(). Предположим, таблица MySQL с именем user_info состоит из двух полей: user_id и page_data. Пользовательский UID, хранящийся в cookie на компьютере пользователя, применяется для загрузки сеансовых данных, хранящихся в поле page_data. В этом поле хранится закодированная строка переменных, одна из которых($bgcolor) содержит цвет фона, выбранный пользователем.
Листинг 13.7. Восстановление сеансовых данных, хранящихся в базе данных MySQL
<?
// Предполагается, что переменная $usr_id(с уникальным
// идентификатором пользователя) хранится в cookie
// на компьютере пользователя.
$id = session_id($usr_id);
// Подключиться к серверу MySQL и выбрать базу данных users
@mysq]_pconnect("localhost", "web", "4tf9zzzf")
or die("Could not connect to MySQL server!");
@mysql_select_db("users") or die("Could not select company database!");
// Выбрать данные из таблицы MySQL
$query = "SELECT page_data FROM user_info WHERE user_id= '$id'",
Sresult = mysql_query($query);
$user_data = mysql_result($result, 0. "page_data");
// Восстановить данные
session_decode($user_data);
// Вывести одну из восстановленных сеансовых переменных
print "BGCOLOR: $bgcolor";
?>
Как видно из двух приведенных листингов, функции session_ encode() и ses-sion_decode() обеспечивают очень удобные и эффективные сохранение и загрузку сеансовых данных.
Назад |
Содержание раздела |
Общее Содержание |
Вперед
Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
|