Библиотека сайта rus-linux.net
Управление сессиями в PHP, часть 2: Сессии на стороне сервера
Оригинал: Session Management Using PHP, Part 2: Server-side Sessions
Автор: V. Nagaradjane
Дата публикации: 1 Января 2009 г.
Перевод: А.Панин
Дата перевода: 5 Марта 2013 г.
Первую часть статьи смотрите здесь:
"Управление сессиями в PHP, часть 1: Сессии на основе кук".
Механизм управления сессиями на стороне сервера является безопасным механизмом сессий. Сессия, открытая с использованием данной техники охватывает ряд страниц, загружаемых с помощью различных браузеров (Firefox, Konqueror, Opera или даже IE). Это означает, что сессия будет действительной даже в том случае, если один из браузеров аварийно завершится и страница с тем же URL будет загружена с помощью другого браузера. Настройки безопасности системы клиента не оказывают влияния на процесс работы данного механизма управления сессиями.
Для получения всех этих преимуществ нам придется потратить время на написание дополнительных строк кода и создание одной дополнительной таблицы базы данных. Таблица с именем session_log создается в базе данных с именем session и должна содержать столбцы для храниения значений идентификаторов сессий, идентификаторов пользователей, IP-адресов удаленных систем, состояния сессий (перечисления значений VALID и EXPIRED с соответствующими числовыми значениями 1 и 2), отметок времени начала сессии и последнего доступа. Записи в таблице session_log создаются сценарием для входа в систему и обновляются сценарием для получения состояния сессии.
Код HTML для ввода имени пользователя и пароля приведен ниже (он сохранен в файле с именем dbloginform.html):
Внешний вид страницы для входа в систему показан на Рисунке 1.
Рисунок 1: Предложение ввода пароля, выводимое при открытии файла dbloginform.html
Вход в систему
Процесс входа в систему реализован в рамках сценария dblogin.php, который принимает имя пользователя и пароль и проверяет корректность этой пары строк. После этого генерируется идентификатор сессии, который должен являться уникальным числом. В нашем случае была вызвана функция microtime() с аргументом 'true', а возвращенное значение было помещено в строковую переменную $t. Цикл while выполняется до того момента, как идентификатор сессии помещается в базу данных. Страница приветствия показана на Рисунке 2, а сценарий для входа в систему приведен ниже:
Рисунок 2: Страница приветствия при использовании механизма управления сессиями на стороне сервера
Сценарий для входа в систему получает IP-адрес клиента из глобальной переменной массива $_SERVER[REMOTE_ADDR]. Идентификатор пользователя извлекается из таблицы пользователей. Отметки времени начала сессии и последнего доступа к ее данным также добавляются в таблицу базы данных. Сценарий начинает работу с условного перехода if в конце сценария, вызывает функцию dblogin() и ожидает логического значения результата, возвращаемого этой функцией. Функция возвращает истинное значение только в том случае, если все операции проверки завершились успешно.
Проверка состояния сессии
Переход по ссылке 'Check session status!' перемещает пользователя на страницу, генерируемую сценарием проверки состояния сессии с именем dbloginstatus.php. Этот сценарий проверяет, соответствует ли действительная сессия IP-адресу машины клиента, запросившего страницу. Действие сессии может быть приостановлено либо с помощью сценария dblogout.php (при переходе по ссылке, либо напрямую по URL), либо после истечения периода неактивности. Период неактивности устанавливается с помощью переменной $time_out, значение которой является максимальным разрешенным периодом времени работоспособности сессии после последнего доступа к ее данным. В данном случае период неактивности был установлен равным 120 секундам для быстрой проверки вывода сообщения о истечении данного периода. Однако, в случае разработки реальных проектов, данное время может варьироваться от 1200 секунд (20 минут) до 2400 секунд (40 минут).
Сообщения, выводимые в случае работы с действительными и истекшими сессиями, показаны на Рисунках 3 и 4 соответственно. Сценарий проверки состояния, приведенный ниже, должен включаться в начало всех страниц, которые должны быть защищены от доступа неавторизованных пользователей:
Сценарий начинает работу с условного перехода if в конце. Для проверки состояния сессии сценарий устанавливает, является ли сессия действительной и не истекло ли ее время. Соответствующие сообщения выводятся в обоих случаях. Если сессия действительна, сценарий устанавливает время последнего доступа к данным сессии в таблице session_log, в соответствии с текущим временем.
Рисунок 3: Проверка работоспособности сессии
Рисунок 4: Проверка состояния для сессии с истекшим периодом неактивности
Защита содержимого страницы с помощью сессий на стороне сервера
После создания сценариев для входа в систему, проверки состояния сессий и завершения сессий, возможна реализация системы защиты для для страниц, аналогичной системе, используемой совместно с механизмом управления сессиями на основе кук (описанной в предыдущей статье). Вызов функции require_once('dbloginstatus.php') в начале сценариев для генерации защищенных страниц позволяет быть уверенным в том, что только авторизованные пользователи получат доступ к их содержимому:
Защищенная страница в случае действительной сессии показана на Рисунке 5, а в случае недействительной сессии - на Рисунке 6.
Рисунок 5: Защищенное содержимое страницы (dbprotectedimage.php) в случае действительной сессии
Рисунок 6: Защищенное содержимое в случае недействительной сессии
Закрытие сессии на стороне сервера
Сессия может быть закрыта с помощью перехода по URL сценария dblogout.php, который устанавливает значение состояния сессии EXPIRED (или числовое значение 2). После вызова сценария dblogout.php становится невозможным доступ к любой из защищенных страниц. На Рисунках 7 и 8 показаны страница закрытия сессии и выводимое при вызове сценария dbloginstatus.php после закрытия сессии сообщение соответственно. Код сценария dblogout.php представлен ниже:
Рисунок 7: Сообщение о закрытии сессии
Рисунок 8: Сообщение о состоянии сессии после ее завершения
Сценарий закрытия сессии устанавливает значение EXPIRED в качестве состояния сессии и устанавливает время последнего доступа к данным сессии равным текущему времени. Если сессия уже была завершена или истек ее период неактивности, сценарий закрытия сессии выведет соответствующее сообщение и завершит работу. На Рисунке 9 представлены строки таблицы session_log. Эта таблица предназначена как для записи времени открытия сессии и последнего доступа к ее данным для пользователей, так и для реализации безопасного механизма хранения данных текущей сессии.
Рисунок 9: Данные сессий при их реализации на стороне сервера
Достоинства и недостатки механизма управления сессиями на стороне сервера
Формирование сессий на стороне сервера является наиболее безопасной стратегией работы с сессиями. Эта стратегия надежна, так как она никоим образом не зависит от настроек кук. Обычно серверы лучше защищены от проникновений злоумышленников. Следовательно, вероятность доступа неавторизованных лиц к данным сессий крайне ограничена. Однако, для реализации данного механизма управления сессиями от разработчика может потребоваться больший объем кода.
После рассмотрения стратегий управления сессиями на стороне клиента и сервера, уверен, что вы без труда сможете защитить данные ваших проектов от просмотра неавторизованными пользователями. Хотя реализация механизма управления сессиями на стороне сервера немного утомительна и занимает время, она в некоторых условиях работает лучше реализации на основе кук.