это хороший подход для входа пользователя? - PullRequest
1 голос
/ 26 марта 2011

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

Заранее спасибо!

session_start();

/* connect to the db */
define("INCLUDED-PUBLIC", true);
include('dbConnection.php');   

/* define safe variables */
$login = mysqli_real_escape_string($connection, $_POST['login-email']);
$pass = md5($_POST['login-pass']);

/* send the query */
$query = mysqli_query($connection, "
  SELECT `user_id`
    FROM `users`
   WHERE `user_contact_email`='$login'
     AND `user_password`='$pass'
   LIMIT 1
");

/* does such account exist? */
$count = mysqli_num_rows($query);

if ($count > 0){

   /* user exists, loggin' in! */
   $data = mysqli_fetch_array($query);
   $userID = $data['user_id'];
   $_SESSION['user']['user_id'] = $userID;

}

Ответы [ 4 ]

2 голосов
/ 26 марта 2011

На самом деле, есть куда улучшаться.

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

Второе: Вы должны получить значение user_password из БД и выполнить сравнение на стороне PHP.

Важно

Заявления, которые вызывают PASSWORD (), могут быть записаны в журналах сервера или в файле истории, например ~ / .mysql_history, что означает, что пароли могут быть прочитаны любым, кто имеет доступ к этой информации. См. Раздел 5.3.2, «Защита паролем в MySQL».

Источник: http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html#function_password

В-третьих: Не используйте MD5 Это хороший алгоритм хеширования, но он считается нарушенным в целях безопасности. Если вы используете PHP 5.3 или новее, используйте crypt , с CRYPT_BLOWFISH.
CRYPT_BLOWFISH в PHP является реализацией хеша Bcrypt. Bcrypt основан на блочном шифре Blowfish и использует дорогостоящую настройку ключей для замедления алгоритма.

Также: не используйте LIMIT в своем запросе, вместо этого наложите УНИКАЛЬНОЕ ограничение на user_contact_email. Использование LIMIT - это уловка, которая может маскировать дубликаты электронных писем пользователей и приводить к неожиданным результатам, когда дубликаты электронной почты каким-либо образом вводятся.

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

1 голос
/ 26 марта 2011

Вещи к изменениям

  • include изменить на require_once
  • убедитесь, что пароль и адрес электронной почты не пусты
  • Вы также проверяете действительный адрес электронной почты, но неверный пароль
  • освободить результирующий набор после сохранения в сеансе
  • закрыть соединение mysqli
  • если пользователь / электронная почта недействительны, чем отправить обратно

мой путь:

session_start();



require_once('dbConnection.php');
/* connect to the db */
define("INCLUDED-PUBLIC", true);


/* define safe variables */
if(!empty($_POST['login-pass']) && !empty($_POST['login-email']) )
{
    $login = mysqli_real_escape_string($connection, $_POST['login-email']);
    $pass = md5($_POST['login-pass']);

    /* send the query */
    $query = mysqli_query($connection, "
      SELECT `user_id`
        FROM `users`
       WHERE `user_contact_email`='$login'
            AND `user_password`='$pass'
        LIMIT 1
    ");

    /* does such account exist? */
    $count = mysqli_num_rows($query);

    if ($count > 0){
       /* user exists, loggin' in! */
       $data = mysqli_fetch_array($query);
       $_SESSION['user']['user_id'] = $data['user_id'];        
       /* free result set */
       mysqli_free_result($query);
       mysqli_close($connection);
    }
    else {
            header("location:login.php");
            exit();
    }

}
1 голос
/ 26 марта 2011

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

  • подсчет строк не требуется, выборка массива будет делать то же самое с более коротким кодом.
  • требуется некоторая обработка ошибок. Вы должны проверить результат запроса и вызвать ошибку, если она не удалась
  • структура кода и удобочитаемость.
    Написание читаемого кода позволяет опускать очевидные комментарии. include('dbConnection.php'); говорит само за себя, не так ли?
    Переменная $ query в вашем коде содержит не запрос, а результат запроса. Итак, вы запутываете свой собственный код, делая его менее читабельным. Всегда используйте разумные имена, это избавит вас от ненужных комментариев.

как это

define("INCLUDED-PUBLIC", true);
include('dbConnection.php');   
$login = mysqli_real_escape_string($connection, $_POST['login-email']);
$pass  = md5($_POST['login-pass']);

$query = "SELECT `user_id` FROM `users` WHERE `user_contact_email`='$login'
                                               AND `user_password`='$pass'";

$result = mysqli_query($connection, $query);
if (!$result) trigger_error(mysqli_error($connection).$query);

if ($data = mysqli_fetch_array($query)){
   session_start();
   $_SESSION['user']['user_id'] = $data['user_id'];
}

Однако, есть некоторые концептуальные улучшения, которые можно сделать

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

сравните ваш код с этим:

define("INCLUDED-PUBLIC", true);
include('dbConnection.php');   
$pass  = md5(SITE_SALT.$_POST['login-email'].$_POST['login-pass']);
$query = "SELECT `user_id` FROM `users` WHERE `user_contact_email`=? AND `user_password`=?";
$data  = dbgetone($query, $_POST['login-email'],$pass);
if ($data){
   session_start();
   $_SESSION['user']['user_id'] = $data['user_id'];
}
1 голос
/ 26 марта 2011

Единственное, что я хотел бы изменить:

$pass = md5($_POST['login-pass']);

На что-то вроде:

$pass = hash('whirlpool', $_POST['login-pass']);

А также изменить способ хранения в базе данных при регистрации.

Кроме этого, все хорошо.

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