Материал: Опорник

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

4.3 Видалення змінних сесії

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

Функція session_unregister(ім’я_змінної) видаляє глобальну змінну з поточної сесії (тобто видаляє її із списку зареєстрованих змінних). Якщо реєстрація проводилася з допомогою $_SESSION ( $HTTP_SESSION_VARS для версії PHP 4.0.6 і більш ранніх), то використовують мовну конструкцію unset(). Вона не повертає ніякого значення, а просто знищує вказані змінні.

Де це може стати в нагоді? Наприклад, для знищення даних про відвідувача (зокрема, логіна і пароля) після його відходу з секретної сторіночки. Якщо правильні логін і пароль збережуться і вікно браузера після відвідин сайту не закрили, то будь-який інший користувач цього комп'ютера зможе прочитати закриту інформацію.

Приклад 12.4. Знищення змінних сесії

У файл secret_info.php додамо строчку для виходу на головну сторінку:

<?php

// ... php код

?>

<html>

<head><title>Secret info</title></head>

// тут розташовується секретна інформація :)

<а href="index.php">На главную</a>

</html>

Приклад 12.4a. secret_info.php

В Index.php знищимо логін і пароль, введений раніше:

<?

session_start();

session_unregister('passwd');

// знищуємо пароль

unset($_SESSION['login']);

// знищуємо логін

print_r($_SESSION);

// виводимо глобальні змінні сесії

?>

<html>

<head><title>My home page</title></head>

// домашня сторіночка

</html>

Приклад 12.4b. Index.php

Тепер, щоб потрапити на секретну сторінку, потрібно буде знову вводити логін і пароль.

Для того, щоб скинути значення всіх змінних сесії, можна використовувати функцію 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 "<hr>";

session_unset();

// знищуємо всі глобальні змінні сесії

print_r($_SESSION);

echo session_id();

echo "<hr>";

session_destroy(); // знищуємо сесію

print_r($_SESSION);

echo session_id();

?>

Приклад 12.5. Знищення сесії і глобальних змінних

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

5 Безпека

Взагалі кажучи, слід розуміти, що використовування механізму сесій не гарантує повної безпеки системи. Для цього потрібно вживати додаткові заходи. Звернемо увагу на проблеми з безпекою, які можуть виникнути при роботі з сесіями і, зокрема, з тими програмами, що ми написали.

По-перше, небезпечно передавати туди-сюди пароль, його можуть перехопити. Крім того, ми зареєстрували його як глобальну змінну сесії, значить, він зберігся в cookies на комп'ютері-клієнті. Це теж погано. І взагалі, паролі і логіни по-хорошому повинні зберігатися в базі даних. Хай інформація про користувачів зберігається в базі даних "test" (в таблиці "users"), а ми маємо до неї доступ під логіном my_user і паролем my_passwd.

По-друге, що робити, якщо хтось написав скрипт підбору пароля для секретної сторінки? В цьому випадку на сторінку авторизації багато раз повинен стукатися якийсь сторонній скрипт. Тому потрібно просто перевіряти, чи з нашого сайту прийшов запит на авторизацію, і якщо ні, то не пускати його далі. Адресу сторінки, з якою надійшов запит, можна одержати за допомогою глобальної змінної $_SERVER['HTTP_REFERER']). Хоча, звичайно, якщо за злом сайту узялися всерйоз, то значення цієї змінної теж підмінять (наприклад, за допомогою того ж PHP). Проте перевірку її значення можна вважати одним з найважливіших кроків на шляху до забезпечення безпеки свого сайту.

<?

session_start();

// створюємо нову сесію або відновлюємо поточну

$conn = mysql_connect("localhost", "my_user","my_passwd");

// встановлюємо з'єднання з сервером БД

mysql_select_db("test");

// вибираємо робочу базу даних

$SERVER_ROOT = "http://localhost/~vasia/tasks/sessions/";

/* за допомогою регулярного виразу $SERVER_ROOT і функції eregi перевіряємо чи починається адреса скрипта, з рядка $SERVER_ROOT (як у нас) */

if(eregi("$SERVER_ROOT" == $_SERVER['HTTP_REFERER'])){

// якщо так, то робимо майже те ж, що і раніше, пароль реєструвати не будемо

if (!isset($_POST['go'])){

echo "<form method=POST >

Login: <input type=text name=login>

Password: <input type=password name=passwd>

<input type=submit name=go value=Go>

</form>";

}else {

/* запит до бази даних: вибираємо з таблиці users login, який співпадає з переданим за запитом, причому пароль у нього теж повинен співпасти з введеним користувачем. Якщо цього нема, то вважаємо, що логін і пароль введені невірно */

$sql = "SELECT login FROM users

WHERE login='" . $_POST['login'] . "' AND passwd='" . $_POST['passwd'] . "';";

$q = mysql_query($sql,$conn); // відправляємо запит до БД

$n = mysql_num_rows($q); // число рядків відповідає на запит

if (!$n==0){

$_SESSION['user_login']=$_POST['login'];

// реєструємо змінну login

Header("Location: secret_info.php");

// перенаправляємо на сторінку secret_info.php

}else echo "Невірні дані, спробуйте ще раз<br>";

}

print_r($_SESSION); // виводимо всі змінні сесії

}

?>

Лістинг 12.6. authorize.php

Неначебто перші дві проблеми вирішено. Але є ще одна. Що робити, якщо хакер просто допише в рядок запиту значення якої-небудь глобальної змінної (наприклад, логіна)? Взагалі це можливо, тільки якщо register_globals=On. Просто інакше ми використовуємо для роботи з глобальними змінними масив $_SESSION і з ним такі фокуси не проходять. Все ж таки спробуємо розв'язати і цю проблему. Для цього потрібно очистити рядок запиту перед тим, як порівнювати значення параметрів. Тобто спочатку скинемо значення $user_login. Потім дану змінну потрібно знову зареєструвати, але не як нову, а як вже існуючу. Для цього знак долара при реєстрації не опускається. Ось що вийшло:

<?php

unset($user_login); // знищуємо змінну

session_start(); // створюємо нову сесію або відновлюємо поточну

session_register($user_login);

// реєструємо змінну як вже існуючу

if (!($user_login=="pit")) // перевіряємо логін

Header("Location: authorize.php");

// якщо помилка, то перенаправляємо на сторінку авторизації

?>

<html>

<head><title>Secret info</title></head>

151

Источник: https://tut-files.ru/previewfile/153681