×
Закрытие
×

Дополнительные материалы бесплатно предоставляются только зарегистрированным пользователям.

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

Для тех кто не зарегистрирован, можно это сделать на вкладке Регистрация.

  • Создаем сайт для работы в Интернете

    1. Причины создания пошаговой инструкции по разработке самописного сайта
    2. Тема создаваемого сайта
    3. В чем будет заключаться монетизация
    4. Функционал
    5. Этапы создания
    6. Текущее состояние создаваемого сайта

    Здравствуйте уважаемый посетитель!

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

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

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

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

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

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

Самописный сайт своими руками!

Текущее состояние создаваемого сайта

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

Где в дополнительных материалах можно бесплатно скачать исходные файлы сайта с таблицами MySQL.

Вы здесь: Главная → Сборник статей → Авторизация  → Управляем доступом к сессии с помощью временных меток


Автор: / Дата:

Управляем доступом к сессии с помощью временных меток

Здравствуйте уважаемый посетитель!

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

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

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

Содержание


  • Механизм управления доступом к сессии с помощью временных меток
  • Дополняем систему авторизации проверкой на активность пользователя
  • Проверяем автоматическое уничтожение сессии в случае достижения порога не активности пользователя.
  • Исходные файлы сайта

Механизм управления доступом к сессии с помощью временных меток


Механизм работы данного функционала несложен и состоит всего из нескольких простых действий:

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

    Рис.1 Проверка отсутствия активности пользователя

    И в зависимости от результата возможны два варианта:
    • 2.1. В случае, если время не активности пользователя достигло значения установленного порога, соответствующего времени жизни сессии, то такая сессия должна быть уничтожена, а доступ к данным PHP-переменных запрещен.
    • 2.2. Если же время отсутствия активности пользователя не превысило порог, то временная метка последней активности обновляется, а дальнейшая работа системы авторизации происходит в штатном режиме.
  3. Дополнительно к этим действиям следует изменить ранее установленное значение времени жизни сессионной cookies. А, именно: вместо ранее заданного времени нужно установить его равным 0. Тем самым время жизни cookie будет установлено на все время до закрытия браузера (контроль теперь будет осуществляться на стороне сервера).

Таким образом, используя данный механизм можно быть уверенным, что, если даже встроенный "сборщик мусора" не успеет вовремя удалить из хранилища файл устаревшей сессии, то все равно она будет уничтожена при первой же попытке ее активировать.

Дополняем систему авторизации проверкой на активность пользователя


Алгоритм работы функционала по контролю на активность пользователя мы рассмотрели, и теперь можно перейти к практической реализации.

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

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

  1. <?php

  2. require_once "start.php";

  3. if (!empty($_POST["auth-button"])) {

  4. //----Получение введенных в форму данных логина и пароля-------------

  5. if (isset($_POST["auth-login"])) $auth_login = $_POST["auth-login"];

  6. else

  7. $auth_login = $_POST["auth-login"];

  8. $auth_login = check_symbol($auth_login, "Логин", "1", "0");

  9. if (isset($_POST["auth-password"])) $auth_password = $_POST["auth-password"];

  10. else

  11. $auth_password = $_POST["auth-password"];

  12. $auth_password = check_symbol($auth_password, "Пароль", "1", "0");

  13. //----Извлечение хеш-строки из базы данных по логину из формы----

  14. $table = "orders";

  15. $column = "client-login";

  16. $value = $auth_login;

  17. $data_bd = getLine($table, $column, $value);

  18. $password_hash = $data_bd["password-hash"];

  19. echo nl2br("Извлеченный из базы данных хеш пароля: ".$password_hash. "\n\n");

  20. //----Формирование хеша пароля из формы-----

  21. $full_salt = substr($password_hash, 0, 29);

  22. $new_hash = crypt($auth_password, $full_salt.'$');

  23. //----Проверка на совпадение хеша пароля из формы с хеш-строкой из базы данных----

  24. if (!empty($password_hash) && $password_hash == $new_hash) { //При успешной аутентификации

  25. session_start(); //Создаем сессию

  26. $key1_hash = hash('sha256', microtime()); //Формируем одноразовый хеш-ключ

  27. setcookie ("key1", $key1_hash, time()+900, "/", $_SERVER['SERVER_NAME'], 0, 1); //Отправляем на сторону клиента cookie с созданным одноразовым ключем

  28. $_SESSION['key1'] = $key1_hash; //Записываем данные ключа в переменную сессии с именем "key1"

  29. $_SESSION['login'] = $auth_login; //Сохраняем в переменной сессии логин пользователя

  30. $_SESSION['agent'] = $_SESSION["HTTP_USER_AGENT"]; //Записываем данные по HTTP-заголовку User-Agent в переменную сессии

  31. $_SESSION['lasttime'] = time(); //Устанавливаем в переменной сессии временную метку последней активности пользователя

  32. if ($auth_login == 'admin') { //Если логин соответствует учетной записи администратора

  33. $addr = $_SERVER['REMOTE_ADDR']; //Получаем данные IP-адреса пользователя

  34. //$addr = '192.54.12.23'; //Вариант с фиксированным значением IP-адреса

  35. $reg_addr = preg_replace("/[^0-9]/", "", $addr); //Преобразуем адрес по регулярному выражению

  36. $addr_hash = hash('sha256', $reg_addr); //Формируем хеш адреса

  37. $_SESSION['addr'] = $addr_hash; //Записываем данные хеша адреса в переменную сессии

  38. }

  39. }

  40. else { //При неправильном вводе логина и/или пароля

  41. setcookie ("alert", "Неверные Логин и/или Пароль!", time()+60, "/", $_SERVER['SERVER_NAME']); //Передаем сообщение об ошибке

  42. }

  43. }

  44. //----Редирект на предыдущую страницу----

  45. header ("Location: ".$_SERVER["HTTP_REFERER"]);

  46. exit;

  47. ?>

Рис.2 Запись в переменную сессии временной метки последней активности пользователя (добавлено в файл auth.php)

Таким образом в обработчике формы в переменной сессии $_SESSION['lasttime'] мы установили временную метку, соответствующую последней активности пользователя (поз.31). После чего можно перейти к обработке полученных данных.

Для этого дополним файл "check_auth.php" кодом (выделен светлым фоном), предназначенным для выполнения действий по пунктам 2, 2.1, 2.2 алгоритма.

  1. <?php

  2. $session_check = 0; //Устанавливаем запрещающий флаг авторизации

  3. if (isset($_COOKIE['alert'])) { //При наличии cookie 'alert' с сообщением об ошибке

  4. $GLOBALS['alert'] = $_COOKIE['alert']; //Для вывода в диалоговое окно браузера записываем в глобальную переменную $GLOBALS['alert'] ообщения об ошибке

  5. setcookie ("alert", "", time()-60*60*24, "/", $_SERVER['SERVER_NAME']); //Удаляем cookie 'alert'

  6. }

  7. else {

  8. if (!empty($_COOKIE[ini_get('session.name')])) { //Если существует активная сессия

  9. session_start(); //Возобновляем сессию

  10. if (isset($_SESSION['key1'])) $session_key1 = $_SESSION['key1']; //Если переменная "key1" в сессии существует, то PHP-переменной $session_key1 присваивается ее значение

  11. else //Если нет

  12. $session_key1 = ""; //Переменной $session_key1 присваивается пустое значение

  13. if (isset($_COOKIE['key1'])) $cookie_key1 = $_COOKIE['key1']; //Если cookie "key1" существует, то PHP-переменной $cookie_key1 присваивается ее значение

  14. else //Если нет

  15. $cookie_key1 = ""; //Переменной $cookie_key1 присваивается пустое значение

  16. if ($session_key1 != "" && $cookie_key1 != "" && $session_key1 == $cookie_key1) { //Если одноразовый ключ сессии и cookie совпадают (подтверждение подлинности пользователя)

  17. $key1_hash = hash('sha256', microtime()); //Формируем одноразовый хеш-ключ

  18. setcookie ("key1", $key1_hash, 0, "/", $_SERVER['SERVER_NAME'], 0, 1); //Отправляем на сторону клиента cookie со вновь созданным одноразовым ключем

  19. $_SESSION["key1"] = $key1_hash; //Записываем данные ключа в переменную сессии с именем "key1"

  20. if (isset($_SESSION['agent'])) { //Проверяем, определена ли переменная сессии, содержащая данные HTTP-заголовка User-Agent

  21. $agent = $_SERVER['HTTP_USER_AGENT']; //Получаем данные об агенте из запроса

  22. if ($_SESSION['agent'] == $agent) { //Если данные об агенте совпадают с данными сессии

  23. $session_check = 1; //Устанавливаем разрешающий флаг авторизации

  24. }

  25. else { //Если данные об агенте не совпадают с данными сессии

  26. $error_auth = 'Подпись пользователя не подтверждена. В целях безопасности текущая сессия закрыта!\nДля получения прав доступа необходимо вновь авторизоваться через соответствующую форму.'; //Сообщение об ошибке

  27. sessionDelete($error_auth); //Вызываем функцию уничтожения сессии

  28. }

  29. }

  30. else { //Если переменная сессии, содержащая данные HTTP-заголовка User-Agent не определена

  31. $error_auth = 'Отсутствует подпись пользователя. В целях безопасности текущая сессия закрыта!\nДля получения прав доступа необходимо вновь авторизоваться через соответствующую форму.'; //Текст сообщения об ошибке

  32. sessionDelete($error_auth); //Вызываем функцию уничтожения сессии

  33. }

  34. $session_time = 900; //Устанавливаем порог отсутствия активности сессии

  35. if (isset($_SESSION['lasttime'])) { //Проверяем, определена ли переменная сессии с меткой времени

  36. if (time() - $_SESSION['lasttime'] < $session_time) { //Если время не активности сессии не превысило установленный порог

  37. $_SESSION['lasttime'] = time(); //Устанавливаем новую метку времени в переменную сессии

  38. }

  39. else { //Если время не активности сессии превысило установленный таймаут

  40. $session_check = 0; //Устанавливаем запрещающий флаг авторизации

  41. $error_auth = 'Время жизни сессии истекло. В целях безопасности текущая сессия закрыта!\nДля получения прав доступа необходимо вновь авторизоваться через соответствующую форму.'; //Сообщение об ошибке

  42. sessionDelete($error_auth); //Вызываем функцию уничтожения сессии

  43. }

  44. }

  45. if (isset($_SESSION['addr'])) { //Проверяем, определена ли переменная сессии с данными IP-адреса пользователя

  46. $addr = $_SERVER['REMOTE_ADDR']; //Получаем данные IP-адреса пользователя

  47. //$addr = '192.54.12.23'; //Вариант с фиксированным значением IP-адреса

  48. $reg_addr = preg_replace("/[^0-9]/", "", $addr); //Преобразуем адрес по регулярному выражению

  49. $addr_hash = hash('sha256', $reg_addr); //Формируем хеш адреса

  50. if ($_SESSION['addr'] != $addr_hash) { //Если данные хеша IP-адреса не совпадают с данными сессии

  51. $session_check = 0; //Устанавливаем запрещающий флаг авторизации

  52. $error_auth = 'Попытка несанкционированного входа в систему. В целях безопасности текущая сессия закрыта!\nДля получения прав доступа необходимо вновь авторизоваться через соответствующую форму.'; //Сообщение об ошибке

  53. sessionDelete($error_auth); //Вызываем функцию уничтожения сессии

  54. }

  55. }

  56. }

  57. else { //При не подтверждении подлинности пользователя

  58. $error_auth = 'Достоверность пользователя не подтверждена. В целях безопасности текущая сессия закрыта!\nДля получения прав доступа необходимо вновь авторизоваться через соответствующую форму.'; //Текст сообщения об ошибке

  59. sessionDelete($error_auth); //Вызываем функцию уничтожения сессии

  60. }

  61. }

  62. }

  63. ?>

Рис.3 Проверка активности пользователя (добавлено в файл check_auth.php)

Где в строке 36 с помощью условного оператора if определяется, достиг ли таймаут не активности пользователя установленного порога.

А затем, в зависимости от результата, либо сессия уничтожается (поз.42) с выводом соответствующего сообщения (поз.41) и установкой запрещающего флага сессии (поз.40). Либо временная метка обновляется и продолжается дальнейшее стандартное выполнение скрипта (поз.37).

Таким образом проверку на активность пользователя мы сделали, осталось только в соответствии с пунктом 3 алгоритма изменить время жизни cookies.

Сделать это достаточно просто. Для сессионной cookie достаточно в директиве session.gc_maxlifetime файла ".htaccess", которую мы установили на этапе создания системы авторизации, изменить прежнее значение на 0.

  1. php_value session.cookie_lifetime 0

Рис.4 Изменение значения времени жизни сессионной cookie в файле .htaccess

Либо вообще можно удалить из файла данную строку, так как значение 0 для этой директивы установлено по умолчанию.

А для cookie, предназначенной для одноразового ключа, изменить прежнее значение на 0 нужно в функции setcookie в одном из ее параметре, определяющем время жизни cookie (поз.18, рис.3).

Проверяем автоматическое уничтожение сессии в случае достижения порога не активности пользователя.


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

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

А для того, чтобы быть уверенным, что мы оперируем с нужной, конкретной сессией, то временно разместим, как это мы делали раньше, в шаблоне главной странице с помощью конструкции echo nl2br код для вывода на страницу соответствующего идентификатора.

  1. . . .

  2. <body>

  3. <?php

  4. echo nl2br("\n Идентификатор сессии: " . session_id() . "\n\n");

  5. ?>

  6. <div "wrapper">

  7. . . .

Рис.5 Вывод на страницу идентификатора текущей сессии (добавлено в файл index.php)

После этого дополнения можно будет увидеть на странице сайта идентификатор сессии авторизованного пользователя.

Вывод на страницу сайта идентификатора сессии

Рис.6 Вывод на страницу сайта идентификатора сессии

А теперь найдем на сервере соответствующий файл.

Ранее, во вводной статье по авторизации пользователей было показано, как можно посмотреть текущие настройки PHP, из которых по параметру "session.save_path" можно также найти и путь к каталогу, предназначенному для хранения файлов сессий.

В данном случае для сайта, размещенного на локальном веб-сервере Open Server местом хранения является папка с директорией: /OSPanel/userdata/temp/. Здесь мы и попробуем найти соответствующий файл.

Файл вновь созданной сессии в хранилище

Рис.7 Файл вновь созданной сессии в хранилище

Как видно, файл с тем же самым идентификатором в хранилище создан.

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

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

Сообщение о закрытии устаревшей сессии при попытке ее активировать

Рис.8 Сообщение о закрытии устаревшей сессии при попытке ее активировать

А также удалить из хранилища и файл сессии.

Отсутствие в хранилище файла устаревшей сессии

Рис.9 Отсутствие в хранилище файла устаревшей сессии

Как видно, система авторизации с использованием временных меток отработала должным образом. Предотвратив тем самым попытку использования сессии с истекшим сроком жизни. И обеспечив при этом запрет доступа к ней и уничтожение файла из хранилища.

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


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

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

Исходные файлы сайта


Знак папкиИсходные файлы сайта с обновлениями, которые были сделаны в данной статье, можно скачать из прилагаемых дополнительных материалов:

  • Файлы каталога www
  • Таблицы базы данных MySQL

При этом, временно сформированные в данной статье PHP-скрипты, размещенные в файле "main.php" папки "articles" корневого каталога, закомментированы. Для проверки рассмотренных здесь примеров, следует раскомментировать соответствующие фрагменты кода.

Дополнительные материалы бесплатно предоставляются только зарегистрированным пользователям.

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

Для тех кто не зарегистрирован, можно это сделать на вкладке Регистрация.

С уважением, Николай Гришин


Комментарии


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

Буду Вам за это очень признателен!

comments powered by HyperComments