Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Безопасный логин

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: Безопасная авторизация - это действительно так сложно?
jaroslav.tavgen
Отправлено: 02 Января, 2015 - 20:10:46
Post Id


Новичок


Покинул форум
Сообщений всего: 8
Дата рег-ции: Янв. 2015  


Помог: 0 раз(а)




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

Посмотрел в Google, как сделать этот процесс наиболее безопасным. И ахнул: Google мне выдал вот такую бандуру: http://www[dot]wikihow[dot]com/Create-a-[dot][dot][dot]in-PHP-and-MySQL (первый результат по запросу в Google "PHP secure login")

У меня вопрос: действительно ли для безопасной авторизации нужно делать ВСЁ ЭТО? Или можно обойтись чем-то попроще, и безопасность всё равно будет соблюдена?

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

(Отредактировано автором: 02 Января, 2015 - 20:17:47)

 
 Top
kotyara1979
Отправлено: 02 Января, 2015 - 20:39:19
Post Id


Частый гость


Покинул форум
Сообщений всего: 247
Дата рег-ции: Окт. 2012  


Помог: 7 раз(а)




Цитата:
при этом их вариант не работает: редирект на нужную страницу делается с помощью header, который не передаёт сессии, а проверка на то, залогинился ли пользователь, делается именно по сессии


Переадресация через header и не должна передавать сессию. Сессия вообще не передается никак. Это сгенерённая кука в браузере. И при старте сессии пхп просто проверяет есть такая запись и соответствует ли она существующим записям на сервере.

А вообще безопасность - это та вещь, где не экономят. Вопрос только в целесообразности накручивания механизмов: насколько "вкусные" вещи лежат за паролем, сколько времени люди захотят потратить на взлом, сколько времени вам понадобится на восстановление сломанного.

Короче каждый решает сам.


-----
Сделать можно все. Главное одеть каску.
 
 Top
jaroslav.tavgen
Отправлено: 02 Января, 2015 - 21:00:26
Post Id


Новичок


Покинул форум
Сообщений всего: 8
Дата рег-ции: Янв. 2015  


Помог: 0 раз(а)




kotyara1979 пишет:
Переадресация через header и не должна передавать сессию. Сессия вообще не передается никак. Это сгенерённая кука в браузере. И при старте сессии пхп просто проверяет есть такая запись и соответствует ли она существующим записям на сервере.

В их варианте после того, как пользователь ввёл правильные логин и пароль, делается переадресация:

PHP:
скопировать код в буфер обмена
  1.    if (login($email, $password, $mysqli) == true) {
  2.         // Login success
  3.         header('Location: ../protected_page.php');


А страница protected_page.php вызывает функцию из другого файла, в которой делается следующая проверка:

PHP:
скопировать код в буфер обмена
  1.     if (isset($_SESSION['user_id'],
  2.                         $_SESSION['username'],
  3.                         $_SESSION['login_string'])) {


Переменной $_SESSION при этом не существует (проверял с помощью echo get_defined_vars()), поэтому страница всегда выдаёт надпись "You are not logged in".

kotyara1979 пишет:
А вообще безопасность - это та вещь, где не экономят. Вопрос только в целесообразности накручивания механизмов: насколько "вкусные" вещи лежат за паролем, сколько времени люди захотят потратить на взлом, сколько времени вам понадобится на восстановление сломанного.

Короче каждый решает сам.

Я ничего не имею против максимального обеспечения безопасности. Проблема в том, что я не понимаю, что должен делать тот код, а если его просто тупо скопировать (что я и сделал) - он не работает... Ну вот проверяет этот код наличие superglobal $_SESSION, которой не существует независимо от того, залогинен ты или нет - и как мне понять, почему этот скрипт не работает так, как должен?

(Отредактировано автором: 02 Января, 2015 - 21:07:28)

 
 Top
esterio
Отправлено: 02 Января, 2015 - 21:13:24
Post Id



Активный участник


Покинул форум
Сообщений всего: 5025
Дата рег-ции: Нояб. 2012  
Откуда: Украина, Львов


Помог: 127 раз(а)




jaroslav.tavgen пишет:
(при этом их вариант не работает: редирект на нужную страницу делается с помощью header, который не передаёт сессии, а проверка на то, залогинился ли пользователь, делается именно по сессии).

передаються не сессии а кука с ИД сессии. передаете не вы, а браузер в заголовках запроса (исключением являеться инициализация сессии).
jaroslav.tavgen пишет:
Переменной $_SESSION при этом не существует (проверял с помощью echo get_defined_vars()), поэтому страница всегда выдаёт надпись "You are not logged in".

Это суперглобальный массив. он всегда существует
jaroslav.tavgen пишет:
залогинен ты или нет - и как мне понять, почему этот скрипт не работает так, как должен?
jaroslav.tavgen пишет:
if (isset($_SESSION['user_id'],
$_SESSION['username'],
$_SESSION['login_string'])) {

примерно так проверяеться, а не проверкой ести ли массив $_SESSION. правда достаточно просто проверить ИД

(Отредактировано автором: 02 Января, 2015 - 21:14:09)

 
 Top
kotyara1979
Отправлено: 02 Января, 2015 - 21:15:01
Post Id


Частый гость


Покинул форум
Сообщений всего: 247
Дата рег-ции: Окт. 2012  


Помог: 7 раз(а)




Проверьте как отрабатывается старт сессии. В вашем случае, за это отвечает функция sec_session_start(). Посмотрите, что она делает, доходит ли там до старта сессии.

Глобальный массив _SESSION будет доступен только при старте сессии.

(Отредактировано автором: 02 Января, 2015 - 21:16:22)



-----
Сделать можно все. Главное одеть каску.
 
 Top
jaroslav.tavgen
Отправлено: 02 Января, 2015 - 21:20:57
Post Id


Новичок


Покинул форум
Сообщений всего: 8
Дата рег-ции: Янв. 2015  


Помог: 0 раз(а)




esterio пишет:
Это суперглобальный массив. он всегда существует

echo (get_defined_vars()) не показывает его. А указанный мной выше "if isset..." даёт FALSE.

kotyara1979 пишет:
Проверьте как отрабатывается старт сессии. В вашем случае, за это отвечает функция sec_session_start(). Посмотрите, что она делает, доходит ли там до старта сессии.

Как это можно проверить?
 
 Top
esterio
Отправлено: 02 Января, 2015 - 21:25:34
Post Id



Активный участник


Покинул форум
Сообщений всего: 5025
Дата рег-ции: Нояб. 2012  
Откуда: Украина, Львов


Помог: 127 раз(а)




jaroslav.tavgen пишет:
echo (get_defined_vars()) не показывает его. А указанный мной выше "if isset..." даёт FALSE.

а session_start не забили?
 
 Top
jaroslav.tavgen
Отправлено: 02 Января, 2015 - 21:26:52
Post Id


Новичок


Покинул форум
Сообщений всего: 8
Дата рег-ции: Янв. 2015  


Помог: 0 раз(а)




Весь процесс происходит так: заходишь на файл login.php. Вводишь логин и пароль. Скрипт перенаправляет тебя на страницу /includes/process_login.php, которая выглядит очень просто:

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. include_once 'db_connect.php';
  3. include_once 'functions.php';
  4.  
  5. sec_session_start(); // Our custom secure way of starting a PHP session.
  6.  
  7. if (isset($_POST['email'], $_POST['p'])) {
  8.     $email = $_POST['email'];
  9.     $password = $_POST['p']; // The hashed password.
  10.  
  11.     if (login($email, $password, $mysqli) == true) {
  12.         // Login success
  13.        header('Location: ../protected_page.php');
  14.     } else {
  15.         // Login failed
  16.         header('Location: ../login.php?error=1');
  17.     }
  18. } else {
  19.     // The correct POST variables were not sent to this page.
  20.     echo 'Invalid Request';
  21. }


(Если в ней поставить echo (get_defined_vars()), то переменная $_SESSION существует, а вот на protected_page.php - уже нет)

Проверка осуществляется с помощью функции login - функция, которая находится в functions.php и выглядит так:

PHP:
скопировать код в буфер обмена
  1. function login($email, $password, $mysqli) {
  2.     // Using prepared statements means that SQL injection is not possible.
  3.     if ($stmt = $mysqli->prepare("SELECT id, username, password, salt
  4.        FROM members
  5.       WHERE email = ?
  6.        LIMIT 1")) {
  7.         $stmt->bind_param('s', $email);  // Bind "$email" to parameter.
  8.         $stmt->execute();    // Execute the prepared query.
  9.         $stmt->store_result();
  10.  
  11.         // get variables from result.
  12.         $stmt->bind_result($user_id, $username, $db_password, $salt);
  13.         $stmt->fetch();
  14.  
  15.         // hash the password with the unique salt.
  16.         $password = hash('sha512', $password . $salt);
  17.         if ($stmt->num_rows == 1) {
  18.             // If the user exists we check if the account is locked
  19.             // from too many login attempts
  20.  
  21.             if (checkbrute($user_id, $mysqli) == true) {
  22.                 // Account is locked
  23.                 // Send an email to user saying their account is locked
  24.                 return false;
  25.             } else {
  26.                 // Check if the password in the database matches
  27.                 // the password the user submitted.
  28.                 if ($db_password == $password) {
  29.                     // Password is correct!
  30.                     // Get the user-agent string of the user.
  31.                     $user_browser = $_SERVER['HTTP_USER_AGENT'];
  32.                     // XSS protection as we might print this value
  33.                     $user_id = preg_replace("/[^0-9]+/", "", $user_id);
  34.                     $_SESSION['user_id'] = $user_id;
  35.                     // XSS protection as we might print this value
  36.                     $username = preg_replace("/[^a-zA-Z0-9_\-]+/",
  37.                                                                 "",
  38.                                                                 $username);
  39.                     $_SESSION['username'] = $username;
  40.                     $_SESSION['login_string'] = hash('sha512',
  41.                               $password . $user_browser);
  42.                     // Login successful.
  43.                     return true;
  44.                 } else {
  45.                     // Password is not correct
  46.                     // We record this attempt in the database
  47.                     $now = time();
  48.                     $mysqli->query("INSERT INTO login_attempts(user_id, time)
  49.                                    VALUES ('$user_id', '$now')");
  50.                     return false;
  51.                 }
  52.             }
  53.         } else {
  54.             // No user exists.
  55.             return false;
  56.         }
  57.     }
  58. }
  59.  

Функция старта сессии sec_session_start() тоже находится в functions.php и выглядит так:
PHP:
скопировать код в буфер обмена
  1. function sec_session_start() {
  2.     $session_name = 'sec_session_id';   // Set a custom session name
  3.     $secure = SECURE;
  4.     // This stops JavaScript being able to access the session id.
  5.     $httponly = true;
  6.     // Forces sessions to only use cookies.
  7.     if (ini_set('session.use_only_cookies', 1) === FALSE) {
  8.         header("Location: ../error.php?err=Could not initiate a safe session (ini_set)");
  9.         exit();
  10.     }
  11.     // Gets current cookies params.
  12.     $cookieParams = session_get_cookie_params();
  13.     session_set_cookie_params($cookieParams["lifetime"],
  14.         $cookieParams["path"],
  15.         $cookieParams["domain"],
  16.         $secure,
  17.         $httponly);
  18.     // Sets the session name to the one set above.
  19.     session_name($session_name);
  20.     session_start();            // Start the PHP session
  21.     session_regenerate_id();    // regenerated the session, delete the old one.
  22. }

(Добавление)
esterio пишет:
jaroslav.tavgen пишет:

echo (get_defined_vars()) не показывает его. А указанный мной выше "if isset..." даёт FALSE.


а session_start не забили?


protected_page.php:
PHP:
скопировать код в буфер обмена
  1.  
  2. <?PHP
  3. include_once 'includes/db_connect.php';
  4. include_once 'includes/functions.php';
  5. sec_session_start();
  6. ?>
  7. <!DOCTYPE html>
  8. <html>
  9.     <head>
  10.         <meta charset="UTF-8">
  11.         <title>Secure Login: Protected Page</title>
  12.         <link rel="stylesheet" href="styles/main.css" />
  13.     </head>
  14.     <body>
  15.         <?PHP if (login_check($mysqli) == true) : ?>
  16.             <p>Welcome <?PHP echo htmlentities($_SESSION['username']); ?>!</p>
  17.             <p>
  18.                 This is an example protected page.  To access this page, users
  19.                 the user, so pages will be able to determine the type of user
  20.                 must be logged in.  At some stage, we'll also check the role of
  21.                 authorised to access the page.
  22.             </p>
  23.             <p>Return to <a href="index.php">login page</a></p>
  24.         <?PHP else : ?>
  25.             <p>
  26.                 <span class="error">You are not authorized to access this page.</span> Please <a href="index.php">login</a>.
  27.             </p>
  28.         <?PHP endif; ?>
  29.     </body>
  30. </html>

(Добавление)
Функция login_check:
PHP:
скопировать код в буфер обмена
  1. function login_check($mysqli) {
  2.     // Check if all session variables are set
  3.     if (isset($_SESSION['user_id'],
  4.                         $_SESSION['username'],
  5.                         $_SESSION['login_string'])) {
  6.                                                 echo 1;
  7.  
  8.         $user_id = $_SESSION['user_id'];
  9.         $login_string = $_SESSION['login_string'];
  10.         $username = $_SESSION['username'];
  11.  
  12.         // Get the user-agent string of the user.
  13.         $user_browser = $_SERVER['HTTP_USER_AGENT'];
  14.  
  15.         if ($stmt = $mysqli->prepare("SELECT password
  16.                                      FROM members
  17.                                      WHERE id = ? LIMIT 1")) {
  18.             // Bind "$user_id" to parameter.
  19.             $stmt->bind_param('i', $user_id);
  20.             $stmt->execute();   // Execute the prepared query.
  21.             $stmt->store_result();
  22.  
  23.             if ($stmt->num_rows == 1) {
  24.                 // If the user exists get variables from result.
  25.                 $stmt->bind_result($password);
  26.                 $stmt->fetch();
  27.                 $login_check = hash('sha512', $password . $user_browser);
  28.  
  29.                 if ($login_check == $login_string) {
  30.                     // Logged In!!!!
  31.                     return true;
  32.                 } else {
  33.                     // Not logged in
  34.                     return false;
  35.                 }
  36.             } else {
  37.                 // Not logged in
  38.                 return false;
  39.             }
  40.         } else {
  41.             // Not logged in
  42.             return false;
  43.         }
  44.     } else {
  45.         echo 2;
  46.         // Not logged in
  47.         return false;
  48.     }
  49. }
  50.  

(Отредактировано автором: 02 Января, 2015 - 21:34:17)

 
 Top
kotyara1979
Отправлено: 02 Января, 2015 - 21:38:41
Post Id


Частый гость


Покинул форум
Сообщений всего: 247
Дата рег-ции: Окт. 2012  


Помог: 7 раз(а)




А у вас вывод ошибок включен?
error_reporting, какой уровень?


-----
Сделать можно все. Главное одеть каску.
 
 Top
jaroslav.tavgen
Отправлено: 02 Января, 2015 - 21:42:40
Post Id


Новичок


Покинул форум
Сообщений всего: 8
Дата рег-ции: Янв. 2015  


Помог: 0 раз(а)




Насчёт $_SESSION, конечно, перепутал: она действительно всегда существует, но на странице /includes/process_login.php в ней есть значения, а на странице protected_page.php она пустая...

kotyara1979 пишет:
А у вас вывод ошибок включен?
error_reporting, какой уровень?

Какой уровень error_reporting не знаю (узнаю чуть позже), но ошибки выводятся.
 
 Top
jaroslav.tavgen
Отправлено: 03 Января, 2015 - 21:49:55
Post Id


Новичок


Покинул форум
Сообщений всего: 8
Дата рег-ции: Янв. 2015  


Помог: 0 раз(а)




echo error_reporting() даёт ответ 30711
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Вопросы новичков »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB