Механизм сессий в PHP. Использование сессий - Работа с сессиями PHP

  • 02.08.2019

С помощью сессии PHP сервер идентифицирует вас и позволяет выполнять необходимые операции: изменение информации на различных веб-страницах, добавление новой информации и т.д. После завершения работы на сайте вы удаляете текущую сессию, нажав на кнопку «Выйти »:

Что такое сессия PHP?

Сессия PHP представляет собой способ хранения информации в переменных сессии, которые могут быть использованы для аутентификации на нескольких веб-страницах. В отличие от куков, информация сессии не хранится на компьютере пользователя. Вместо этого сессия создает файл на сервере во временном каталоге.

Эта информация, хранимая на протяжении сессии, доступна для всех веб-страниц ресурса. На сервере расположение временного файла определяется параметром session.save_path в конфигурационном файле php.ini .

При создании PHP-сессии выполняются следующие три действия:

  • Когда создается сессия, PHP генерирует уникальный идентификатор, который представляет собой случайную строку из 32 шестнадцатеричных чисел. Идентификатор времени жизни сессии PHP выглядит примерно так: 9c8foj87c3jj973actop1re472e8774 ;
  • Сервер отправляет на компьютер пользователя куки, называемые PHPSESSID , для хранения строки уникального идентификатора сессии;
  • Сервер генерирует в указанном временном каталоге файл, который содержит имя уникального идентификатора сессии с префиксом sess _g. sess_9c8foj87c3jj973actop1re472e8774 .

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

Пользователь может завершить сеанс, нажав кнопку выхода из системы, которая вызывает функцию session_destroy() . Когда пользователь закрывает браузер, сессия PHP закрывается автоматически. Иначе сервер завершит сессию по истечении заданного периода времени.

Синтаксис сессий в PHP

При PHP авторизации через сессию она создается с помощью функции session_start() и удаляется с помощью функции session_destroy() . Глобальная переменная PHP , известная под именем $_SESSION , используется для установки значений переменных сессии. Сбросить все значения, установленные для переменных сессии, можно с помощью функции session_unset() .

Операции сессии

Мы рассмотрим следующие операции с использованием сессии PHP , а также их примеры.

  • Запуск сессии PHP и установка ее переменных сессии: новая сессия PHP запускается с помощью функции session_start() . После того, как сессия была создана, можно установить значения ее переменных сессии с помощью $_SESSION . Мы установили значения для переменных “userID ” — “php_user ” и “password ” — “tutorials ”:

PHP-сессии - создание Сессия PHP начата и переменные сессии заданы!"; ?>

Результат : в результате запуска приведенного выше PHP-кода на сервере будет выведено следующее сообщение:


  • Получение значений переменных сессии PHP : Можно получить значения переменных, которые мы установили во время последней PHP сессии авторизации. Когда мы открываем PHP-сессию в начале каждой страницы (session_start () ), должен указываться код, приведенный ниже. Мы извлекаем и выводим эти значения с помощью глобальной переменной $_SESSION :

PHP-сессия - получение значений
"; echo "Пароль - " . $_SESSION["password"] . "."; ?>

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


  • Обновление значений переменных сессии PHP : Во время сессии можно обновить значения ее переменных. Сначала нам нужно открыть PHP-сессию в начале каждой страницы (session_start () ). В приведенном ниже коде мы обновляем значения переменных “userID ” — “new_php_user ” и “password ” — “education ”.

Можно вывести массив переменных сессии и их значений с помощью функции print_r($ _SESSION) , как показано ниже:

PHP-сессия - изменение значений
"; print_r($_SESSION); ?>

Результат : когда мы запустим на сервере приведенный выше PHP код, мы получим следующее сообщение. В нем будет приведен массив переменных сессии с их новыми значениями:


  • Удаление сессии PHP и сброс всех значений переменных сессии: Можно сбросить сессию PHP с помощью функции session_unset() и удалить текущую сессию с помощью функции session_destroy() :

PHP-сессия - удаление
Сессия PHP и все переменные сессии были успешно удалены!

"; ?>

Результат: когда мы запустим на веб-сервере приведенный выше PHP-код , в результате он выведет следующее сообщение:


Заключение

В этой статье мы рассказали о различных функциях для работы с сессиями PHP , их синтаксисе. В отличие от куков, информация сессий хранится на стороне сервера. Благодаря этому сессии PHP более надежны.

Сессии позволяют установить связь между посетителем и сайтом при помощи идентификатора сессии .

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

Идентификатор сессии, хранящийся на компьютере пользователя, это файл cookie .

Cookie хранится в браузере пользователя, при этом соответствующий файл создается и на сервере.

Создаем сессию

Самый простой способ открытия сессии заключается в использовании функции session_start:

// инициировать сессию session_start();

Эта функция проверяет, существует ли идентификатор сессии, и, если нет, то создает его. Если идентификатор текущей сессии уже существует, то загружаются зарегистрированные переменные сессии.

Данная конструкция (для каждой страницы нужно вызвать один раз) должна быть вызвана до любого вывода (это правило работает и для setcookie()), включая пробелы.

Когда создается сессия в браузер ‛прилетает“ кука следующего вида:

PHP

echo "Имя сессии: ".session_name(). " Идентификатор сессии: ".session_id(); // Имя сессии: PHPSESSID Идентификатор сессии: mceu820l02id3ds0vcvtgnht04

Создаем переменную сессии

Переменная сессии создается путем добавлением какого-либо значения суперглобальному массиву $_SESSION:

$_SESSION["nick"] = $_POST["name"];

Уничтожаем переменные сессии и саму сессию

1 . Удалить переменную сессии можно следующим образом:

Unset($_SESSION["nick"]);

Этим мы предотвратим повторное использование информации.

Но лучше просто очистить массив $_SESSION (удалить все переменные сессии):

//очистить массив $_SESSION $_SESSION = array();

2 . Также необходимо сделать следующее:

Установить файл cookie сессии недействительным:

If (isset($_COOKIE)) { // session_name() - получаем название текущей сессии setcookie(session_name(), "", time()-86400, "/"); }

Имя сессии ссылается на session id в куках и URL

3 . Уничтожить (завершить) сессиию

Session_destroy();

Буферизация вывода

Если у вас уже есть какой-либо вывод, вы можете воспользоваться фукцией ob_start() . Данная функция делает буферизацию вывода. Теперь вывод не будет отправлен браузеру, пока вы не отправите его принудительно при помощи функции ob_end_flush() .

"; unset($_SESSION["nick"]); if (isset($_COOKIE)) { setcookie(session_name(), "", time()-86400, "/"); // содержимое сессии - пустая строка } // setcookie сработает безошибочно, так как мы только сейчас ob_end_flush(); // отправили браузеру вывод session_destroy();

С другой стороны, не всегда необходимо использовать функцию ob_end_flush() , так как интерпретатор PHP автоматически очистит буфер по выполнению сценария.

Пересоздаем идентификатор сессии

При каждом входе в систему необходимо, в целях безопасности, пересоздавать идентификатор сессии. Информация в переменных сессии сохраняется, меняется лишь идентификатор сессии . Не забывайте, информация о сессии хранится на веб-сервере в виде текста в соответствующем файле. Чтобы пересоздать идентификатор вызовите session_regenerate_id() и обновите текущую страницу или перенаправьте пользователя на другую страницу.

Механизм работы сессий


Уменьшаем время жизни сессии

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

$_SESSION["start"] = time(); // временная метка авторизации пользователя $now = time(); // текущее время $time_limit = 1000; // максимально допустимое время бездействия пользователя в сек. if ($now > $_SESSION["start"] + $time_limit) { echo "Ваше время истекло"; //....... // и удаляем сессию и ее cookie } else { $_SESSION["start"] = time(); } // если порядок, обновляем

Как сделать время жизни сессии вечной?

Для того чтобы клиент оставался всегда залогиненным, не надо делать время жизни сессии вечной. Сессия - на то она и сессия, чтобы начаться, когда клиент пришел, и завершиться, когда клиент ушел.

Когда клиент пришел вновь - надо начать новую сессию, но загрузить в неё данные о клиенте, основываясь на уникальной для клиента куке, которая надолго устанавливается ему при выборе галочки, например, "запомнить меня".

Работа с сессией при отключенных куках

Если для настройки session.use_trans_sid установить 1 , то при отключенных куках PHP будет передавать PHPSESSID методом GET в строке запроса.

Создание сессии

Первое, что нужно сделать для работы с сессиями (если они уже настроены администратором сервера), это запустить механизм сессий. Если в настройках сервера переменная session.auto_start установлена в значение "0" (если session.auto_start=1, то сессии запускаются автоматически), то любой скрипт, в котором нужно использовать данные сессии, должен начинаться с команды

Session_start();

Получив такую команду, сервер создает новую сессию или восстанавливает текущую, основываясь на идентификаторе сессии, переданном по запросу. Как это делается? Интерпретатор PHP ищет переменную, в которой хранится идентификатор сессии (по умолчанию это PHPSESSID) сначала в cookies, потом в переменных, переданных с помощью POST- и GET-запросов. Если идентификатор найден, то пользователь считается идентифицированным, производится замена всех URL и выставление cookies. В противном случае пользователь считается новым, для него генерируется новый уникальный идентификатор, затем производится замена URL и выставление cookies.

Команду session_start() нужно вызывать во всех скриптах, в которых предстоит использовать переменные сессии, причем до вывода каких-либо данных в браузер. Это связано с тем, что cookies выставляются только до вывода информации на экран.

Получить идентификатор текущей сессии можно с помощью функции session_id().

Для наглядности сессии можно задать имя с помощью функции session_name([имя_сессии]).

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

Пример . Создание сессии

Переименуем наш файл index.html, чтобы обрабатывались php-скрипты, например в Index.php, создадим сессию и посмотрим, какой она получит идентификатор и имя.

session_start();
// создаем новую сессию или
// восстанавливаем текущуюecho session_id();
?>

My home page
... // домашняя страничка

echo session_name();
// выводим имя текущей сессии.
// В данном случае это PHPSESSID
?>

Если проделать то же самое с файлом authorize.php, то значения выводимых переменных (id сессии и ее имя) будут такими же, если перейти на него с index.php и не закрывать перед этим окно браузера (тогда идентификатор сессии изменится).

Регистрация переменных сессии

Однако от самих идентификатора и имени сессии нам пользы для решения наших задач немного. Мы же хотим передавать и сохранять в течение сессии наши собственные переменные (например, логин и пароль).

Для того чтобы этого добиться, нужно просто зарегистрировать свои переменные:

Session_register(имя_переменной1,
имя_переменной2, ...);

Заметим, что регистрируются не значения, а имена переменных. Зарегистрировать переменную достаточно один раз на любой странице, где используются сессии. Имена переменных передаются функции session_register() без знака $.

Все зарегистрированные таким образом переменные становятся глобальными (т.е. доступными с любой страницы) в течение данной сессии работы с сайтом.

Зарегистрировать переменную также можно, просто записав ее значение в ассоциативный массив $_SESSION, т.е. написав

$_SESSION["имя_переменной"] =
"значение_переменой";

В этом массиве хранятся все зарегистрированные (т.е. глобальные) переменные сессии.

Доступ к таким переменным осуществляется с помощью массива $_SESSION["имя_переменной"] (или $HTTP_SESSION_VARS["имя_переменной"] для версии PHP 4.0.6 и более ранних).

Если же в настройках php включена опция register_globals, то к сессионным переменным можно обращаться еще и как к обычным переменным, например так: $имя_переменной.

Если register_globals=off (отключены), то пользоваться session_register() для регистрации переменных переданных методами POST или GET, нельзя, т.е. это просто не работает. И вообще, не рекомендуется одновременно использовать оба метода регистрации переменных, $_SESSION и session_register().

Пример 12.3 . Регистрация переменных
Зарегистрируем логин и пароль, вводимые пользователем на странице авторизации.

session_start();
// создаем новую сессию или
// восстанавливаем текущуюif (!isset($_GET["go"])){
echo "


Login:
Password: name=passwd>

";
}else {
$_SESSION["login"]=$_GET["login"];
// регистрируем переменную login
$_SESSION["passwd"]=$_GET["passwd"];
// регистрируем переменную passwd
// теперь логин и пароль - глобальные
// переменные для этой сессии
if ($_GET["login"]=="pit" &&
$_GET["passwd"]=="123") {
Header("Location: secret_info.php");
// перенаправляем на страницу
// secret_info.php
}else echo "Неверный ввод,
попробуйте еще раз
";
}
print_r($_SESSION);
?>

Теперь, попав на страничку secret_info.php, да и на любую другую страницу сайта, мы сможем работать с введенными пользователем логином и паролем, которые будут храниться в массиве $_SESSION. Таким образом, если изменить код секретной странички (заметьте, мы переименовали ее в secret_info.php) так:

session_start();
// создаем новую сессию или
// выводим все переменные сессии
?>

Secret info

Здесь я хочу делиться секретами с другом Петей.

То мы получим в браузере на секретной странице следующее:

Array ( => pit => 123)
Здесь я хочу делиться секретами с другом Петей.

В итоге получим список переменных, зарегистрированных на authorize.php и, собственно, саму секретную страничку.

Что это нам дает? Допустим, хакер хочет прочитать секреты Васи и Пети. И он как-то узнал, как называется секретная страничка (или странички).

Тогда он может попытаться просто ввести ее адрес в строке браузера, минуя страницу авторизации (ввода пароля). Чтобы избежать такого проникновения в наши тайны, нужно дописать всего пару строк в код секретных страничек:

session_start();
// создаем новую сессию или
// восстанавливаем текущуюprint_r($_SESSION);
// выводим все переменные сессииif (!($_SESSION["login"]=="pit" &&
$_SESSION["passwd"]==123))
// проверяем правильность
// пароля-логина
Header("Location: authorize.php");
// если ошибка, то перенаправляем на
// страницу авторизации
?>

Secret info
... // здесь располагается
//секретная информация:)

Удаление переменных сессии

Кроме умения регистрировать переменные сессии (т.е. делать их глобальными на протяжении всего сеанса работы), полезно также уметь удалять такие переменные и сессию в целом.

Функция session_unregister(имя_переменной) удаляет глобальную переменную из текущей сессии (т.е. удаляет ее из списка зарегистрированных переменных).

Если регистрация производилась с помощью $_SESSION ($HTTP_SESSION_VARS для версии PHP 4.0.6 и более ранних), то используют языковую конструкцию unset(). Она не возвращает никакого значения, а просто уничтожает указанные переменные.

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

Пример 1 . Уничтожение переменных сессии

В файл secret_info.php добавим строчку для выхода на главную страницу:

// ... php код
?>

Secret info
... // здесь располагается
// секретная информация:)
На главную

В Index.php уничтожим логин и пароль, введенные ранее:

session_start();
session_unregister("passwd");
// уничтожаем парольunset($_SESSION["login"]);
// уничтожаем логинprint_r($_SESSION);
// выводим глобальные переменные сессии
?>

My home page
... // домашняя страничка

Теперь, чтобы попасть на секретную страницу, нужно будет опять вводить логин и пароль.

Для того чтобы сбросить значения всех переменных сессии, можно использовать функцию session_unset();

Уничтожить текущую сессию целиком можно командой session_destroy();

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

session_start(); // инициализируем сессию$test = "Переменная сессии";
$_SESSION["test"]= $test;
// регистрируем переменную $test.
// если register_globals=on,
// то можно использовать
// session_register("test");

print_r($_SESSION);
// выводим все глобальные переменные
echo session_id();
// выводим идентификатор сессии
echo "


";
session_unset();
// уничтожаем все глобальные
// переменные сессииprint_r($_SESSION);
echo session_id();
echo "
";
session_destroy(); // уничтожаем сессиюprint_r($_SESSION);
echo session_id();
?>

В результате работы этого скрипта будут выведены три строки: в первой - массив с элементом test и его значением, а также идентификатор сессии, во второй - пустой массив и идентификатор сессии, в третьей - пустой массив. Таким образом, видно, что после уничтожения сессии уничтожается и ее идентификатор, и мы больше не можем ни регистрировать переменные, ни вообще производить какие-либо действия с сессией

С самого начала PHP все приняли на ура, но как только на этом языке стали создавать достаточно крупные проекты, разработчики столкнулись с новой проблемой - в PHP отсутствовало понятие глобальных переменных! То есть, выполнялся некий скрипт, посылал сгенерированную страницу клиенту, и все ресурсы, используемые этим скриптом уничтожались. Попробую проиллюстрировать: предположим есть две страницы одного сайта, index.php и dothings.php. Исходники к этим страницам выглядят так:

index.php dothings.php

Если выполнить эти два скрипта, то на первой странице мы увидим надпись "Меня задали на index.php", а вторая страница будет пустой.

Разработчики web-сайтов, недолго думая, стали использовать cookie для хранения глобальных переменных на стороне клиента. Процесс выглядел примерно так: пользователь приходит на главную страницу сайта, делает какие-то действия, и вся информация, связанная с этим пользователем, которая может потребоваться на других страницах сайта, будет храниться у него в браузере в виде cookie. Этот метод имеет довольно серьезные минусы, из-за которых от PHP в своё время отвернулось немало разработчиков. Например, нам нужно авторизовать пользователя, чтобы разрешить ему доступ к закрытым (или принадлежащим только ему) разделам сайта. Придется отправлять пользователю cookie, который будет служит его последующим идентификатором на сайте. Такой подход становится очень громоздким и не удобным, как только сайт начинает собирать всё больше и больше сведений о поведении пользователя, ведь всю информацию, посылаемую пользователю, желательно кодировать, чтобы её нельзя было подделать. Ещё совсем недавно подделкой cookie можно было "уложить" не один чат, а порой и пробраться в чужую почту. К тому же есть ещё на свете странные люди, у которых браузер cookie не поддерживает.

Я не буду вдаваться в технологические вопросы устройства механизма работы сессий, а только опишу, как правильно работать с сессиями в PHP.

Как работать с сессиями?

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

"Warning: open(/var/state/php/sess_6f71d1dbb52fa88481e752af7f384db0, O_RDWR) failed: No such file or directory (2)".

Это значит всего лишь, что у вас неправильно настроен PHP. Решить эту проблему можно, прописав правильный путь (на существующую директорию) для сохранения сессий в файле php.ini и перезапустить сервер.

Любой скрипт, который будет использовать переменные (данные) из сессий, должен содержать следующую строчку:

Session_start();

Эта команда говорит серверу, что данная страница нуждается во всех переменных, которые связаны с данным пользователем (браузером). Сервер берёт эти переменные из файла и делает их доступными. Очень важно открыть сессию до того, как какие-либо данные будут посылаться пользователю; на практике это значит, что функцию session_start() желательно вызывать в самом начале страницы, например так:

Session_start(); ?> ... Для задания директории в которой будут сохраняться файлы сессий используется функция session_save_path() : session_save_path($_SERVER["DOCUMENT_ROOT"]."/session"); session_start();

После начала сессии можно задавать глобальные переменные. Ари присвоении какого-либо значения любому полю массива $_SESSION, переменная с таким же именем автоматически регистрируется, как переменная сессии. Этот массив доступен на всех страницах, использующих сессию. Для примера разберем програму:

index.php Всё ОК. Сессию загрузили! Пройдём, посмотрим что там: dothings.php

При последовательном запуске этих файлов, первый скрипт "index.php" выдаст следующий результат:

Всё ОК. Сессию загрузили! Пройдём, посмотрим что там:

А второй "dothings.php" вот это:

Меня задали на index.php

Переменная $a теперь доступна на всех страницах данного сайта, которые запустили сессии.

Другие полезные функции и приемы для работы с сессиями:

  • unset($_SESSION["a"]) - сессия "забывает" значение заданной сессионой переменной;
  • session_destroy () - сессия уничтожается (например, если пользователь покинул систему, нажав кнопку "выход");
  • session_set_cookie_params (int lifetime [, string path [, string domain]]) - с помощью этой функции можно установить, как долго будет "жить" сессия, задав unix_timestamp определяющий время "смерти" сессии. По умолчанию, сессия "живёт" до тех пор, пока клиент не закроет окно браузера.
  • session_write_close () - запись переменных сесии и закрытие ее. Это необходимо для открытия сайта в новом окне, если страница выполняет длительную обработу и заблокировала для вашего браузера файл сессий.

Примеры

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

Авторизация Пользователя

Вопросы по авторизации пользователей с помощью PHP-сессий постоянно задаются в конференциях по web-программированию. Механизм авторизации пользователей в системе с помощью сессий довольно хорош с точки зрения безопасности (см.раздел ).

Наш пример будет состоять из трёх файлов: index.php, authorize.php и secretplace.php. Файл index.php содержит форму, где пользователь введёт свой логин и пароль. Эта форма передаст данные файлу authorize.php, который в случае успешной авторизации допустит пользователя к файлу secretplace.php, а в противном случае выдаст сообщение об ошибке.

Примеры: index.php Вводи пароль

Логин:
Пароль:
authorize.php страницу... header("Location: secretplace.php"); exit; } } // если что-то было не так, то пользователь получит // сообщение об ошибке. ?> Вы ввели неверный пароль! secretplace.php Привет, , ты на секретной странице!!! :)

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

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

  • на компьютере пользователя стоит "троян", который ворует номера сессий;
  • злоумышленник отлавливает трафик между компьютером пользователя и сервером. Конечно, есть защищенный (зашифрованный) протокол SSL, но им пользуются не все;
  • к компьютеру нашего пользователя подошел сосед и стащил номер сессии.

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

Впрочем, PHP очень часто можно "обмануть". Давайте рассмотрим возможные точки взлома в программе авторизации пользователя:

  • Файл authorize.php - попытка подбора пароля с помощью стороннего скрипта;
  • Файл secretplace.php - попытка обмануть программу путём вписывания значений переменной $logged_user в адресной строке браузера, например так:
    "http://www.yoursite.ru/secretplace.php?logged_user=hacker "

Итак, в нашей программе явно видны две "дыры", одна маленькая и не особо заметная, а вот вторая - просто огромная, через которую большинство хакеров и лезет туда, куда не надо.

Как "залатать" дыру номер 1?

Не будем писать тонны кода по блокировке IP-адреса и т.п., а просто проверим, откуда приходит запрос, а точнее с какой страницы пришёл запрос, если это будет любая страница с нашего сайта, то всё нормально, а во всех остальных случаях пускать не будем. Подкорректируем файл authorize.php:

authorize.php V2 страницу... header("Location: secretplace.php"); exit; } } } ?> Вы ввели неверный пароль!
Как избавиться от "дыры" номер 2?

Предположим, у вас есть сайт, где каждый смертный может зарегистрироваться чтобы добавлять сообщения в форум. Естественно, в форуме у некоторых пользователей (админов, модераторов), возможностей больше чем у других, они, например, могут удалять сообщения других пользователей. Уровень доступа пользователя вы храните в сессии, в переменной $user_status, где $user_status = 10 соответствует полному доступу к системе. Пришедшему на сайт злоумышленнику достаточно зарегистрироваться штатным образом, а потом дописать в адресной строке браузера ?user_status=10 . Вот и завёлся у вас на форуме новый админ!

В принципе, любую переменную скрипта можно задать через адресную строку, просто дописав после полного адреса к скрипту вопросительный знак и название переменной с её значением. Давайте поправим наш код, чтобы этого избежать:

secretplace.php V2 переменную unset($_SESSION["logged_user"]); // открываем сессию session_start(); /* просто зайти на эту страницу нельзя... если имя пользователя не зарегистрировано, то перенаправляем его на страницу index.php для ввода логина и пароля... тут на самом деле можно много чего сделать, например запомнить IP пользователя, и после третьей попытки получить доступ к файлам, его перекрыть. */ if(!isset($_SESSION["logged_user"])){ header("Location: index.php"); exit; } ?> Привет, , ты на секретной странице! Итоги

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

Примеры

?>
// Автоматическая вставка SID в ссылки. ini_set("session.use_trans_sid", true); session_start(); ?> Click here!
Click here!!

// Пример работы с сессиями. session_start(); // Если на сайт только-только зашли, обнуляем счетчик. if (!isset($_SESSION["count"])) $_SESSION["count"] = 0; // Увеличиваем счетчик в сессии. $_SESSION["count"] = $_SESSION["count"] + 1; ?>

Счетчик

раз(а).
Закройте браузер, чтобы обнулить счетчик.
" target="_blank"> Открыть дочернее окно браузера.
// Простой пример использования сессий без Cookies. session_name("test"); session_start(); $_SESSION["count"] = @$_SESSION["count"] + 1; ?>

Счетчик

В текущей сессии работы с браузером Вы открыли эту страницу раз(а).
Закройте браузер, чтобы обнулить этот счетчик.
?">Нажмите сюда для обновления страницы!

Как уже известно, протокол HTTP позволяет веб-приложениям устанавливать "сессии" - диалог между клиентом и сервером, причём состояние этого диалога сохраняется от запроса к запросу.

Язык PHP, являясь в основном языком для веб-программирования, предоставляет возможность пользоваться механизмом сессий HTTP, беря на себя большую часть забот при организации и хранении данных сессий. Напомню, что необходимо для работы механизма сессий HTTP:

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

Собственно, единственное действие, которое необходимо предпринять в программе на PHP, чтобы шестерёнки механизма сессий закрутились - вызвать одну-единственную функцию: session_start(). Эта функция проделывает все необходимые действия:

  • Проверяет, не прислал ли клиент номер уже существующей сессии в Cookie или в параметрах запроса. Если клиент прислал номер сессии, то данные этой сессии загружаются из места постоянного хранения (например, файла) в память, и становятся доступны программе через массив $_SESSION. Если клиент не прислал номера сессии или такой сессии не существует на сервере - создаётся новая сессия с новым номером, а её данные также доступны через массив $_SESSION, который в случае новой сессии будет пустым. Номер вновь созданной сессии помещается в поле заголовка ответа сервера Set-Cookie.
  • Обеспечивает сохранение данных сессии. После того, как PHP-программа обработала запрос, текущее состояние массива $_SESSION сохраняется в месте постоянного хранения, чтобы вновь стать доступным при следующем запросе клиента.

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

При первом заходе на эту страничку, сервер пришлёт браузеру куки с номером сессии:

Set-Cookie : PHPSESSID=4ftvca7jmmnm04q95r3sdsk6r6; path=/

И этот же номер сессии браузер будет отправлять обратно серверу при каждом последующем запросе. Теперь, если в браузере очистить куки, на сервере будет создана новая сессия с другим номером, и счёт в нашем тестовом скрипте начнётся заново.

Более реальный пример: логин пользователя

Чаще всего сессии используются при логине пользователя на сайт. При входе на сайт, пользователь вводит логин и пароль, которые проверяет сервер. Если логин правильный, то сервер должен запомнить данные пользователя в сессии, чтобы не спрашивать больше логин с паролем. В простейшем случае получится такой пример:

array("password" => "123", "title" => "Администратор",), "user" => array("password" => "qwe", "title" => "Пользователь",),); return isset($users[$login])? $users[$login]: null; } function getCurrentUser() { $user = isset($_SESSION["user"])? $_SESSION["user"]: null; return $user; } function setCurrentUser($user) { $_SESSION["user"] = $user; } ?>

Привет, !
Ссылка1 Ссылка2

Выйти Вы еще не зашли на сайт. Введите логин и пароль:
Логин: Пароль:

Эта программка запрашивает логин и пароль, причём можно войти с логином user , qwe или admin , 123 . Залогиненному пользователю показывается приветствие. При логине отображается сообщение, если имя пользователя или пароль указаны неверно.

Как только удалось зайти на этот "сайт", можно покликать по ссылкам (Ссылка1, Ссылка2), оставаясь при этом залогиненным пользователем.

Какие данные можно хранить в сессии?

По умолчанию PHP хранит данные сессии во временном файле в виде текста. В этом можно убедиться, заглянув в директорию с временными файлами PHP. Эта директория указана в phpinfo() в разделе Environment, TEMP. В этой директории вы найдёте файлы вида sess_4ftvca7jmmnm04q95r3sdsk6r6 , где 4ftvca7jmmnm04q95r3sdsk6r6 - номер сессии, переданный в Cookie. Загляните в этот файл: если вы запустили самый первый пример выше, то в файле обнаружится примерно такое содержимое: "value|i:2;". Этот текст представляет собой сериализованное представление содержимого сессии, где хранится всего лишь одна переменная с числом.

Все значения, которые PHP-программа помещает в сессию через массив $_SESSION, при сохранении сессии превращаются в текстовый вид, а затем записываются в файл. Процесс преобразования значений переменных в текст называется "сериализацией". Таким образом, в сессию можно поместить любые данные, которые PHP способен сериализовать.

К счастью, в PHP сериализовать можно не только простые значения вроде чисел и строк, но так же и сложные структуры вроде массивов и объектов:

"; print_r($_SESSION); echo ""; $_SESSION["testArray"] = array(1, 2, 3, "one", "two", "three", "child" => array(5, 6, 7),); $obj = new stdClass(); $obj->x = 1234; $obj->y = 4567; $_SESSION["testObject"] = $obj;

Этот пример запишет в файл сессии такие данные:

TestArray|a:7:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;s:3:"one";i:4;s:3:"two";i:5;s:5:"three";s:5:"child";a:3:{i:0;i:5;i:1;i:6;i:2;i:7;}}testObject|O:8:"stdClass":2:{s:1:"x";i:1234;s:1:"y";i:4567;}

Хранение объектов в сессии

В сессии, как видно, можно хранить объекты. Но при этом следует помнить, что сохраняя в сессии объекты, ссылающиеся каким-либо образом на ваши "самодельные" классы, или объекты-экземпляры ваших классов, необходимо, чтобы объявление этих классов делалось до момента вызова session_start(). То есть, PHP должен знать класс до того, как встретит упоминание о нём при десериализации данных сессии.

При сохранении объектов бывают ситуации, когда стандартная сериализация объекта по каким-либо причинам неприемлема или вовсе невозможна. В таких случаях можно реализовать сериализацию вручную, объявив в классе "волшебные" методы __sleep() и __wakeup() .

Кстати , сериализацию возможно осуществлять и "вручную", причём не обязательно для сохранения/загрузки данных сессии. Понадобиться это может, когда некоторые данные в приложении надо сохранить для использования позже, или передать по сети. Функции, которые могут пригодиться при сериализации/десериализации - serialize() , unserialize() , json_encode() , json_decode() .

Что нельзя хранить в сессии?

В сессии нельзя хранить то, что нельзя сериализовать. Примером такой сущности может служить любой ресурс PHP. Ресурсы - это сетевые подключения, дескрипторы открытых файлов, подключения к базе данных и некоторые другие объекты. Ресурс в PHP - это ссылка на внутренний объект в недрах PHP, который не доступен непосредственно из программы, но с которым можно работать, вызывая различные функции PHP. Этакий "чёрный ящик", содержимое которого не может и не должно сериализоваться.

Дополнительные возможности

PHP предоставляет разработчику возможность реализовать свой способ хранения данных сессии, например, в базе данных. Для этого необходимо реализовать функции, которые будут сохранять и загружать данные сессии из места постоянного хранения. Затем об этих функциях надо пообщить PHP, вызвав функцию session_set_save_handler.

Для ускорения процесса сохранения и загрузки данных сессии на высоко нагруженных сайтах может использоваться сервер Memcached, который хранит данные в памяти. Поддержка этого способа хранения сессий встроена в PHP и настраивается через файл конфигурации php.ini.

Можно задать имя параметра Сookie, через который передаётся номер сессии, указав его имя, время жизни, домен и другие параметры.

Эти и многие другие возможности настройки сессий HTTP в PHP доступны через функции session_*.