Что такое управление сеансом.HTTP иногда называют "протоколом без состояния". Это означает, что данный протокол не имеет встроенного способа поддержки состояния между двумя транзакциями. Когда пользователь запрашивает друг за другом две страницы, HTTP не обеспечивает возможности уведомить, что оба запроса исходят от одного и того же пользователя. Таким образом, идея управления сеансами заключается в обеспечении отслеживания пользователя в течение одного сеанса связи с Web-сайтом. Если это удастся осуществить, мы сможем легко поддерживать подключение пользователя и предоставление ему содержимого сайта в соответствии с его уровнем прав доступа или персональными настройками. Мы сумеем отслеживать поведение пользователя.
В более ранних версиях РНР управление сеансами осуществлялось средствами PHPLib, базовой библиотеки РНР, которая и сейчас является полезным набором инструментов. Об этом можно прочесть на
http://phplib.netuse.de/index.php3
Четвертая версия РНР включает собственные встроенные функции управления сеансом. Концептуально они подобны PHPLib, но PHPLib помимо этого обеспечивает em и ряд дополнительных функциональных возможностей. Так что если окажется, что эти собственные функции не вполне отвечают вашим требованиям, ничто не мешает рассмотреть возможность использования PHPLib.
Основные функциональные средства управления сеансом.Для запуска сеанса в РНР используется уникальный идентификатор сеанса, представляющий собой зашифрованное случайное число. Идентификатор сеанса генерируется РНР и сохраняется на стороне клиента в течение всего времени жизни сеанса. Для хранения идентификатора сеанса используется либо cookie-набор на компьютере пользователя, либо URL.
Идентификатор сеанса играет роль ключа, обеспечивающего возможность регистрации некоторых специфических переменных в качестве так называемых переменных сеанса. Содержимое этих переменных сохраняется на сервере. Единственной информацией, "видимой" на стороне клиента, является идентификатор сеанса. Если во время определенного подключения к вашему сайту идентификатор сеанса является "видимым" либо в cookie-наборе, либо в URL, имеется возможность получить доступ к переменным сеанса, которые сохранены на сервере для данного сеанса. По умолчанию переменные сеанса хранятся в двумерных файлах на сервере (при желании способ хранения можно изменить и использовать вместо двумерного файла базу данных, но для этого потребуется написать собственную функцию).
Скорее всего, придется иметь дело с Web-сайтами, на которых для хранения идентификатора сеанса используется URL. Если в вашем URL имеется строка данных, которые выглядят случайными, то это, скорее всего, свидетельствует об использовании одной из двух описанных здесь разновидностей управления сеансом.
Другим решением проблемы сохранения состояния на протяжении некоторого количества транзакций, при наличии чистого внешнего вида URL, являются cookie-наборы.
Что такое cookie-набор?cookie-набор — это небольшой фрагмент информации, который сценарии сохраняют на клиентской машине. Чтобы установить cookie-набор на машине пользователя, необходимо отправить ему HTTP-заголовок, содержащий данные в следующем формате.
Set-Cookie: NAME=VALUE; [expires=DATE;] [path=PATH;] [domain=DOMAIN_NAME;] [secure]
Это создаст cookie-набор с именем NAME и значением VALUE. Все остальные параметры являются необязательными. В expires задается дата истечения срока действия, после наступления которой cookie-набор перестанет рассматриваться как актуальный. Заметим, что если дата истечения срока действия не задана, cookie-набор будет постоянным, пока его кто-нибудь не удалит вручную — либо вы, либо сам пользователь). Два параметра path и domain применяются для определения одного или нескольких URL, к которым относится данный cookie-набор. Ключевое слово secure означает, что cookie-набор не может отправляться через простое HTTP-соединение.
Когда браузер соединяется с URL, он сначала ищет cookie-наборы, хранящиеся локально. Если какие-либо из них относятся к URL, с которым установлено соединение, они передаются обратно на сервер.
Установка cookie-наборов из РНР.cookie-наборы в РНР можно установить вручную, используя функцию setcookie(). Она имеет следующий прототип:
int setcookie (string name [, string value [, int expire [, string path [, string domain [, int secure]]]]])
Параметры в точности соответствуют тем, которые используются в описанном выше заголовке Set-Cookie. Если cookie-набор установлен как
setcookie ("mycookie", "value");
то когда пользователь обращается к следующей странице на вашем сайте (или перезагружает текущую страницу), вы получаете доступ к переменной с именем $mycookie, которая содержит значение "value". Доступ к этой переменной можно получить также через $HTTP_COOKIE_VARS["mycookie"].
Для удаления cookie-набора необходимо вызвать setcookie() с тем же именем, но без указания значения. Если cookie-набор устанавливался с другими параметрами (такими как специфические URL или даты истечения), потребуется отправить те же параметры повторно, иначе cookie-набор удален не будет.
Для установки cookie-набора вручную можно воспользоваться также функцией Header() и описанным выше синтаксисом представления cookie-набора. Однако при этом следует иметь в виду, что заголовки cookie-наборов должны отправляться перед всеми другими заголовками (иначе заголовки cookie-наборов работать не будут).
Использование cookie-наборов в сеансах.При использовании cookie-наборов возникают некоторые проблемы: есть браузеры, которые не принимают cookie-наборы, а есть пользователи, которые запрещают использование cookie-наборов в своих браузерах. Это одна из причин, по которым в сеансах РНР используются двойной метод cookie-набор/адрес URL (ниже этот вопрос рассматривается более подробно).
В сеансе РНР нет необходимости задавать cookie-наборы вручную. Это за вас сделают функции сеанса. Для того чтобы просмотреть содержимое cookie-набора, установленное при управлении сеансом, можно воспользоваться функцией session_get_cookie_params(). Она возвращает ассоциативный массив, содержащий элементы lifetime, path и domain.
Можно использовать также:
session_set_cookie_params($lifetime, $path, $domain);
Этот оператор устанавливает параметры cookie-набора для сеанса.
Если возникнет желание получить более подробную информацию о cookie-наборах, то за консультациями по спецификации cookie-наборов следует обратиться на сайт компании Netscape:
http://home.netscape.com/newsref/std/cookie_spec.html
Сохранение идентификатора сеанса.В РНР cookie-наборы в сеансах используются по умолчанию. Если есть возможность установить cookie-наборы, то для сохранения идентификатора сеанса будет использоваться именно этот способ. Другой метод, который может применяться в РНР, заключается в добавлении идентификатора сеанса к адресу URL. Можно сделать так, чтобы идентификатор сеанса добавлялся к URL автоматически — для этого следует скомпилировать РНР с опцией --enable-trans-sid.
Можно встроить идентификатор сеанса в ссылку, чтобы обеспечить его передачу. Идентификатор сеанса будет запоминаться в константе SID. Для того, чтобы передать его вручную, его потребуется добавить в конец ссылки, аналогично параметру GET:
<А HREF="link.php?<?=SID?>">
В общем случае проще компилировать РНР с --enable-trans-sid, если только это возможно (заметим попутно, что константа SID может использоваться для вышеописанных целей только в том случае, если конфигурация РНР выполнялась с --епаblе-track-vars).
Реализация управления простым сеансом.Основными этапами использования сеанса являются следующие:
· Запуск сеанса
· Регистрация переменных сеанса
· Использование переменных сеанса
· Отмена регистрации переменных и закрытие сеанса
Заметим, что все перечисленные этапы не обязательно могут содержаться в одном сценарии, и некоторые из них могут находиться в нескольких сценариях. Рассмотрим каждый из этих этапов последовательно.
Запуск сеанса.Прежде чем можно будет воспользоваться функциональными возможностями сеанса, следует запустить сам сеанс. Существует три способа сделать это.
Первый (и самый простой) заключается в том, что сценарий начинается с вызова функции
session_start() ;
Эта функция проверяет, существует ли идентификатор текущего сеанса. Если нет, она его создает. Если же идентификатор текущего сеанса уже существует, она загружает зарегистрированные переменные сеанса, чтобы они стали доступными для использования.
Надо отметить, что это прекрасный способ — вызов session_start() в начале сценариев, в которых используются сеансы.
Второй способ заключается в том, что сеанс запускается при попытке зарегистрировать переменные сеанса (см. далее).
Третий способ запустить сеанс — задать установки РНР, при которых сеанс будет запускаться автоматически, как только кто-либо посетит ваш сайт. Для этого следует воспользоваться опцией session.auto_start в файле php.ini (более подробно указанный способ будет описан при рассмотрении конфигурации).
Регистрация переменных сеанса.Для того чтобы получить возможность отслеживать переменные от одного сценария другому, их необходимо зарегистрировать. Это делается путем вызова функции session_register(). Например, для регистрации переменной $myvar применяется следующий код.
$myvar = 5; session_register("myvar");
Обратите внимание: вы должны передать в функцию session_register() строку, содержащую имя переменной. Эта строка не должна включать символ $. Данный оператор регистрирует имя переменной и отслеживает ее значение. Отслеживание переменной будет осуществляться, пока не завершится сеанс либо пока вручную не отменится ее регистрация.
За один прием можно зарегистрировать более одной переменной, передав разделенный запятыми список имен переменных:
session_register("myvar1", "myvar2");
Использование переменных сеанса.Чтобы сделать переменную сеанса доступной для использования, сначала необходимо запустить сеанс, воспользовавшись одним из описанных выше способов. После этого появляется доступ к этой переменной. Если опция register_globals включена, то доступ к этой переменной можно получить через сокращенную форму ее имени, например, $myvar. Если же упомянутая опция не включена, получить доступ к переменной можно через ассоциативный массив $HTTP_SESSION_VARS, например, $HTTP_SESSION_VARS ["myvar"].
Переменные сеанса не могут быть перезаписаны данными GET или POST. Это хорошо с точки зрения обеспечения безопасности, однако сопряжено с некоторыми ограничениями при кодировании.
С другой стороны, от вас потребуется тщательность при проверке на предмет того, установлены ли уже переменные сеанса (например, с использованием isset() либо empty()). Кроме того, следует иметь в виду, что переменные могут быть установлены пользователем через GET или POST. Проверить, является ли переменная зарегистрированной переменной сеанса, можно обратившись к функции session_is_registered(). Вызов функции выполняется следующим образом:
$result = session_is_registered("myvar");
Эта функция проверит, является ли $myvar зарегистрированной переменной сеанса, и вернет true или false. Можно поступить и по-другому — проверить массив $HTTP_SESSION_VARS на предмет наличия в нем переменной.
Отмена регистрации переменных и завершение сеанса.После окончания работы с переменной сеанса ее регистрацию можно отменить, воспользовавшись функцией
session_unregister("myvar");
Подобно функции регистрации, эта функция требует указания имени переменной, регистрацию которой необходимо отменить, в виде строки, не включающей символ $. Данная функция за один раз может отменить регистрацию только одной переменной сеанса (в противоположность session_register()). Однако, для отмены регистрации всех переменных текущего сеанса можно обратиться к session_unset().
По завершении сеанса сначала потребуется отменить регистрацию всех переменных, а затем для обнуления идентификатора сеанса вызвать
session_destroy();
Пример простого сеанса.Изложенный выше материал может показаться несколько абстрактным, поэтому сейчас вашему вниманию предлагается пример. Приведенный в нем код обеспечивает обработку трех страниц. На первой странице мы запустим сеанс и зарегистрируем переменную $sess_var Код показан в листинге 6.15.
Листинг 6.15. page1.php — запуск сеанса и регистрация переменной
<?
session_start ();
session_register("sess_var");
$sess_var = "Hello world!";
echo "The content of \ $sess_var is $sess_var<br>" ;
?>
<a href = "page2.php">Next page</a>
Мы зарегистрировали переменную и установили ее значение.
Заметим, что мы изменили значение переменной уже после ее регистрации. Можно, однако, сделать и наоборот — установить значение, а после этого зарегистрировать переменную. Конечное значение переменной на странице — это то значение, которое будет доступно на последующих страницах. В конце сценария переменная сеанса преобразуется в последовательную форму (сериализуется), или замораживается, до своей перезагрузки через следующий вызов session_start(). Таким образом, следующий сценарий начинается с вызова session_start(). Сценарий показан в листинге 6.16
Листинг 6.16. page2.php — получение доступа к переменной сеанса и отмена регистрации
<?
session_start();
echo "The content of \ $sess_var is $sess_var<br>";
session_unregister("sess_var");
?>
<a href = "page3.php">Next page</a>
После вызова session_start() переменная $sess_var станет доступной, а ее значением будет то, которое сохранено в предыдущем сеансе.
Сделав с переменной все необходимые действия, мы вызываем session_unregister() для отмены ее регистрации. Обратите внимание: сеанс еще существует, но переменная $sess_var уже больше не является зарегистрированной.
И наконец, мы переходим к page3.php, последнему сценарию в рассматриваемом примере.
Листинг 6.17. page3.php — завершение сеанса
<?
session_start();
echo "The content of \ $sess_var is $sess_var<br>";
session_destroy () ;
?>
Как можно видеть, доступа к значению $sess_var больше нет. И в завершение — вызов session_destroy() для разрушения идентификатора сеанса.
Конфигурирование управления сеанса.А сейчас мы предлагаем ознакомиться с набором опций конфигурации для сеансов, которые можно установить в своем файле php.ini. В табл. 7.8 перечисляются некоторые из наиболее полезных опций вместе с их кратким описанием.