РефератыИнформатикаСеСессии в PHP

Сессии в PHP

В разнообразных конференциях, посвященных программированию меня в первую очередь всегда интересуют такие разделы, как "Web-программирование" и "Скрипты". По большей части, вопросы о PHP в таких форумах довольно простые, требующие лишь общего понимания PHP, тем не менее, самый часто задаваемый вопрос по моим наблюдениям, это: "Что такое сессии в PHP и с чем/как их можно кушать?". Хотелось бы разъяснить этот вопрос раз и навсегда.


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


- index.php -


<?php


$a = "Меня задали на index.php";


?>


<html><body>


<?php


echo $a;


?>


</body></html>


- dothings.php -


<html><body>


<?php


echo $a;


?>


</body></html>


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


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


При использовании сессий вся информация хранится не на стороне клиента, а на стороне сервера, и потому лучше защищена от манипуляций злоумышленников. Да и работать с сессиями куда проще и удобнее, так как все данные автоматически проходят через алгоритмы криптографии модуля PHP. В броузере клиента, лишь хранится уникальный идентификатор номера сессии, либо в форме cookie, либо в виде переменной в адресной строке броузера, какой из двух способов использовать для передачи идентификатора сессии между страницами интерпретатор PHPвыбирает сам. Это на 100 безопасно, так как идентификатор сессии уникален, и подделать его практически невозможно (об этом чуть далее, в разделе о безопасности сессий).


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


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


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


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


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


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


session_start();


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


<?php


session_start();


?>


<html>


<head>


</head>


...


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


- index.php -


<?php


// открываем сессию


session_start();


// задаём значение переменной


$a = "Меня задали на index.php";


// регистрируем переменную с открытой сессией


// важно: названия переменных передаются функции session_register()


// беззнака $


session_register("a");


?>


<html>


<body>


Всё ОК. Сессию загрузили!


Пройдём, посмотрим что <a href="dothings.php>там:</a>


</body>


</html>


- dothings.php -


<?php


// открываем сессию


session_start();


?>


<html>


<body>


<?php


echo $a;


?>


</body>


</html>


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


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


А второй (dothings.php) вот это:


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


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


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


session_unregister(string) - сессия <забывает> значение заданной глобальной переменной;


session_destroy() - сессия уничтожается (например, если пользователь покинул систему, нажав кнопку <выход>);


session_set_cookie_params(int lifetime [, string path [, string domain]])-с помощью этой функции можно установить, как долго будет <жить> сессия, задав unix_timestampопределяющий время <смерти> сессии. По умолчанию, сессия <живёт> до тех пор, пока клиент не закроет окно браузера.


Примеры


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


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


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


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


Приступим: - index.php -


<html>


<head>


<title>Введи пароль, смертный</title>


</head>


<body>


<form action="authorize.php" method="post">


Логин:<input type="text" name="user_name"><br>


Пароль:<input type="password" name="user_pass"><br>


<input type="submit" name="Submit">


</form>


</body>


</html>


- authorize.php -


<?php


// открываем сессию


session_start();


// данные были отправлены формой?


if($Submit){


// проверяем данные на правильность... в данном случае я


// вписал имя пользователя и пароль прямо в код, целесообразней


// было бы проверить логин/пароль в базе данных и при сов-


// падениидатьдоступпользователю...


if(($user_name=="cleo")&&($user_pass=="password")){


$logged_user = $user_name;


// запоминаем имя пользователя


session_register("logged_user");


// и переправляем его на <секретную> страницу...


header("Location: secretplace.php");


exit;


}


}


// если что-то было не так, то пользователь получит сообщение об ошибке.


?>


<html><body>


Вы ввели неверный пароль!


</body></html>


- secretplace.php -


<?php


// открываем сессию


session_start();


/*


просто зайти на эту страницу нельзя... если


имя пользователя не зарегистрировано, то


перенаправляем его на страницу index.php


для ввода логина и пароля... тут на самом деле


можно много чего сделать, например запомнить


IP пользователя, и после третьей попытки получить


доступ к файлам, его закрыть.


*/


if(!isset($logged_user)){


header("Location: index.php");


exit;


}


?>


<html>


<body>


Привет, <?php echo $logged_user; ?>, ты на секретной странице!!! :)


</body>


</html>


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


Итак, мы умеем передавать идентификатор от одной страницы (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 -


<?php


// открываем сессию


session_start();


// полный путь к корневой директории где расположены скрипты


$SERVER_ROOT = "http://localhost/test1/";


// если пользователь пришёл с любой страницы нашего сайта


// то он вроде наш...


// Переменная $HTTP_REFERER всегда доступна по умолчанию


// и содержит полный адрес ссылающейся страницы...


// функция eregi() проверяет, начинается ли адрес ссылающейся страницы


// со значения в переменной $SERVER_ROOT


if(eregi("^$SERVER_ROOT",$HTTP_REFERER)){


// данные были отправлены формой?


if($Submit){


// далеевсекакраньше


if(($user_name=="cleo")&&($user_pass=="password")){


$logged_user = $user_name;


// запоминаем имя пользователя


session_register("logged_user");


// и переправляем его на <секретную> страницу...


header("Location: secretplace.php");


exit;


}


}


}


?>


<html><body>


Вы ввели неверный пароль!


</body></html>


Как избавиться от <дыры> номер 2?


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


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


- secretplace.php V2 -


<?php


// убираем всё лишнее из адресной строки


// функция unset() <освобождает> переменную


unset($logged_user);


// открываем сессию


session_start();


// и корректируем испорченные перменные.


// Важно: в этом случае, переменная регистрируется не как новая


// переменная, а как уже существующая, а потому знак $ не опускается


session_register($logged_user);


/*


просто зайти на эту страницу нельзя... если


имя пользователя не зарегистрировано, то


перенаправляем его на страницу index.php


для ввода логина и пароля... тут на самом деле


можно много чего сделать, например запомнить


IP пользователя, и после третьей попытки получить


доступ к файлам, его перекрыть.


*/


if(!isset($logged_user)){


header("Location: index.php");


exit;


}


?>


<html>


<body>


Привет, <?php echo $logged_user; ?>, ты на секретной странице!!! :)


</body>


</html>


Итоги


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


Добавление от 14.12.2001


С выходом в свет PHP 4.1.0 - работа с сессиями значительно облегчилась. Все переменные сессий стали доступны из глобального массива _SESSION['var_name']. Самое приятное наверное в том, что при присвоении какого-либо значения любому полю массива, переменная с таким же именем автоматически регистрируется, как переменная сессии, на пр:


<?


$_SESSION['counter'] = 12;


echo $counter;


?>


выведетнаэкранброузерачисло 12.

Сохранить в соц. сетях:
Обсуждение:
comments powered by Disqus

Название реферата: Сессии в PHP

Слов:1785
Символов:17181
Размер:33.56 Кб.