Реферат Сесії в 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.

Список літератури

Для підготовки даної праці були використані матеріали із сайту http://phpcell.webhost.ru/

Схожі реферати:

Навігація