Внимание! Сайт переехал на новый домен sayt-sozdat.ru. Пожалуйста, обновите страницы закладок с новыми URL
×
Закрытие
3
×

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

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

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

Устанавливаем графический редактор GIMP

  1. Выбор графического редактора
  2. Устанавливаем программу GIMP
  3. Устанавливаем Руководство пользователя

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

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

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

Кроме того здесь можно будет посмотреть, как в этот редактор добавить встроенное "Руководство пользователя", а также приведен бесплатный видеокурс, где можно поближе с ним познакомиться.

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

Cайт на практическом примере

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

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

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

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


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

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

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

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

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

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

Содержание


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

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


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

  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

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

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

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

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


Комментарии


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

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