За последние 24 часа нас посетили 17512 программистов и 1650 роботов. Сейчас ищет 921 программист ...

Форма авторизации, не могу проверить хешированный пароль в базе данных

Тема в разделе "PHP и базы данных", создана пользователем evkon, 22 ноя 2016.

  1. evkon

    evkon Новичок

    С нами с:
    22 ноя 2016
    Сообщения:
    7
    Симпатии:
    0
    Здравствуйте. Пишу форму авторизации. Пользователь находится, но пароль проверку не проходит. Запрос из переменной $query_select_email успешно находит нужную ячейку (проверял через phpMyAdmin), однако password_verify($pwd, $result2) всегда false.

    HTML:
    1. <!DOCTYPE html>
    2.     <meta charset="utf-8">
    3.     <title>Syte</title>
    4.     </style>
    5. </head>
    6.     <form method="post" action="login.php">
    7.         <input type="text" id="user_email" name="user_email" placeholder="e-mail" pattern=".+@.+\..+">
    8.         <input type="password" id="user_password" name="user_password" placeholder="пароль">
    9.         <input type="submit" name="submit" value="войти">
    10.     </form>
    11. </body>
    12. </html>
    13.  

    PHP:
    1. <?php
    2.     require '../db.inc.php';
    3.  
    4.     $email = trim($_POST['user_email']);
    5.     $email = $mysqli->real_escape_string($email);
    6.     $pwd = trim($_POST['user_password']);
    7.     $pwd = $mysqli->real_escape_string($pwd);
    8.     $query_select_email="SELECT email FROM users WHERE email = '$email'";
    9.     $query_select_hash="SELECT pwd FROM users WHERE email = '$email'";
    10.  
    11.     $result = $mysqli->query($query_select_email);
    12. //    $result2 = mysqli_query($mysqli, $query_select_hash);
    13.     $result2 = $mysqli->query($query_select_hash);
    14.  
    15.     if ($result->num_rows == 1) {
    16.         echo 'Такой пользователь есть.';
    17.     }
    18.     else {
    19.         echo 'Такого пользователя нет.';
    20.     }
    21.  
    22.     if (password_verify($pwd, $result2)) {
    23.         echo 'Пароль верный.';
    24.         $query_select_hash->close();
    25.         $mysqli->close();
    26.     }
    27.     else {
    28.         echo 'Пароль неверный!';
    29.         $query_select_hash->close();
    30.         $mysqli->close();
    31.     }
    32. ?>
     
  2. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    сделайте var_dump($result2), будете удивлены.

    $result2 в данном случае не хэш содержит, а ресурс, который, надо обработать, из которого надо сформировать массив результатов, и уже потом, из массива результатов доставать хэш.
    --- Добавлено ---
    Вот вам для затравки: https://php.net/manual/ru/mysqli-result.fetch-array
     
  3. evkon

    evkon Новичок

    С нами с:
    22 ноя 2016
    Сообщения:
    7
    Симпатии:
    0
    Спасибо
    PHP:
    1.     while ($row = $result2->fetch_row()) {
    2.     printf ($row[0]);
    3.     }
    Выводит хеш из таблицы. Только что потом делать? $row[0] уничтожается после завершения цикла, насколько я понимаю.
    И $result тоже нужно обрабатывать?
     
  4. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.819
    Симпатии:
    1.333
    Адрес:
    Лень
    фигово что fetchcolumn в пдо
    $row[0] без цикла посмотри
     
  5. evkon

    evkon Новичок

    С нами с:
    22 ноя 2016
    Сообщения:
    7
    Симпатии:
    0
    Без цикла он мне ничего не выводит.
    fetchColumn - а это довольно интересно. Можно будет им воспользоваться, через PDO я тоже пробовал подключаться.
     
  6. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Как что? Присвоить это значение переменной, объявленной вне цикла.

    PHP:
    1. $query_result = [];
    2. while ($row = $result2->fetch_row()) {
    3.     $query_result[] = $row;
    4.     }
    5. var_dump($query_result[0]);
    Вот и вытащили наружу.
    Любой результат работы БД надо обрабатывать. В итоге вы придете к тому, что напишете свой универсальный обработчик запросов.

    Советовать всем подряд PDO - не правильно, вот что я скажу. Если в проекте не планируется использовать ничего, окромя мускула, PDO - это зло. Ты сейчас возразишь про prepared statement, но они и в mysqli есть.
     
  7. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.819
    Симпатии:
    1.333
    Адрес:
    Лень
    Я про FetchColumn тему веду, причем тут заранее подготовленные запросы?
     
  8. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Ну просто обычно это главный аргумент.
    Просто вот ради этого:
    ворошить PDO, как по мне, нет смысла. Проблемы как таковой и нет.
     
  9. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.819
    Симпатии:
    1.333
    Адрес:
    Лень
    сокращение кода подставляя одну функцию место 3 строчного цикла while, ну да.. нет смысла..
     
  10. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Да, нет. У нас не индия, чтобы приложение по количеству строчек оценивать. К тому же, есть куча готовых классов, а можно и свой написать обработчик, который будет в одну строку все что угодно делать. PDO - монстр, с огромными накладными расходами на свое существование, с огромными оверхедами. Он нужен только если у тебя офигеть кросс-платформа, заточенная на миграцию между разными БД. В любом другом случае он не нужен. Это узкое бутылочное горлышко, существование которого может оправдать только необходимость оперативной миграции.

    Советовать PDO новичкам, которым он во сто лет не пригодится - медвежья услуга.
     
  11. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.819
    Симпатии:
    1.333
    Адрес:
    Лень
    пластинка... где там совет чтобы юзер переходил на пдо ? тут не Индия а Африка оказывается когда говорится одно, а берут и через *опу другое лепят
     
  12. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Ты не оскорбляйся. Ничего, чтобы тебя обидеть, я не написал. Я лишь аргументирую свою точку зрения. И тот факт, что ты всегда всем рекомендуешь PDO, тоже имеет место быть. И ты имеешь на это право - это твое дело, кому что рекомендовать. У тебя есть положительный личный опыт использования PDO, ты им делишься. Ты хочешь, чтобы все были рады как ты. Это ок. И это правильное, хорошее, стремление. Но ты закрываешь глаза на оборатную сторону этой медали. А я ее осветил. Всего лишь описал свою точку зрения на этот счет. Что считаю использование PDO там, где это не оправдано архитектурно, не правильным подходом. Не более.
     
  13. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.819
    Симпатии:
    1.333
    Адрес:
    Лень
    Буду более конкретен :D
    --- Добавлено ---
    ( запрос) - ( фетчКоламн )

    ( запрос )
    (цикл)
    (результат)
     
  14. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Как со стеной.
     
    denis01 нравится это.
  15. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.250
    Адрес:
    там-сям
    девочки не ссорьтесь
    --- Добавлено ---
    проблема топикстартера не в выборе расширения или метода, а в непонимании самого алгоритма. зачем там цикл?

    то же самое с уважаемым советчиком. зачем там подобная "оптимизация", если она не помогает?
    --- Добавлено ---
    @evkon, ты допускаешь, что может быть несколько аккаунтов с одним email? если так, это ошибка проектирования. если сие невозможно, то цикл не нужен.
     
    denis01 нравится это.
  16. evkon

    evkon Новичок

    С нами с:
    22 ноя 2016
    Сообщения:
    7
    Симпатии:
    0
    @artoodetoo, email проверяется на стадии регистрации, поэтому несколько аккаунтов с одним email в базе не может быть. Хорошо, теперь без цикла и оставил только один запрос к базе данных, из него можно вытащить и email, и хеш. Однако всё-равно где-то у меня ошибка, password_verify всегда возвращает false.
    Для поля pwd, где хранится хеш выделил char(255). Я только начал, поэтому ещё многое не знаю.
    PHP:
    1. <?php
    2.     require '../db.inc.php';
    3.  
    4.     $email = trim($_POST['user_email']);
    5.     $email_escape_string = $mysqli->real_escape_string($email);
    6.     $pwd = trim($_POST['user_password']);
    7.     $pwd_escape_string = $mysqli->real_escape_string($pwd);
    8.     $query_select_email="SELECT * FROM `users` WHERE email = '$email_escape_string'";
    9.     $result = $mysqli->query($query_select_email);
    10.  
    11. if ($row = $result->fetch_assoc()) {
    12.     echo 'Такой пользователь есть';
    13.         if (password_verify($pwd_escape_string, $row['pwd']))
    14.              echo '.&nbspи пароль тоже верный.<br/><a href="">На главную!</a>';
    15.         else echo ', но пароль неверный!';}
    16. else
    17.     echo 'Такого пользователя нет.';
    18.  
    19.       $query_select_email->close();
    20.       $mysqli->close();
    21. ?>
     
  17. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.861
    Симпатии:
    657
    В базе хоть хэш хранится? Созданный соотв. ф-цией. Зачем вы пароль эскейпите, если не используете его в запросе?
    --- Добавлено ---
    Это много. Даже для алгоритмов с длинной суммой. Или у вас соль стопудовая?
     
  18. evkon

    evkon Новичок

    С нами с:
    22 ноя 2016
    Сообщения:
    7
    Симпатии:
    0
    Не конвертируется в char (60), мало ему, честно, не считал сколько нужно. Да, вы правы, пароль на стадии сравнения с хешем, наверное, излишне обрабатывать. Хеш в таблице есть, успешно достаётся (на предыдущий странице проверяли), пробовал другие email, не получается.

    PHP:
    1. <?php
    2.     include '../db.inc.php';
    3.     include 'pwgen.class.php';
    4.  
    5.     $email = trim($_POST['email']);
    6.     $email = $mysqli->real_escape_string($email);
    7.     $pwgen = new PWGen();
    8.     $pwd = $pwgen->generate();
    9.       $pwd_hash = password_hash('$pwd', PASSWORD_DEFAULT);
    10.  
    11.     $query_select_email="SELECT email FROM users WHERE email = '$email'";
    12.     $result = $mysqli->query($query_select_email);
    13.  
    14.     if ($result->num_rows >= 1){
    15.         echo "Такой пользователь уже есть!";
    16.         $query_select_email->close();
    17.         $mysqli->close();
    18.     }
    19.     else{
    20.         $mysqli->query("INSERT INTO users (email, pwd) VALUES ('$email', '$pwd_hash')");
    21.         $mysqli->close();
    22.         $subject = "Ты принят!";
    23.         $msg = "Используй для входа e-mail: $email и пароль: $pwd";
    24.         $headers = 'From: *@*.*';
    25.         mail($email, $subject, $msg, $headers);
    26.         printf('Зарегистрирован! Проверь почтовый ящик.<br/><a href="..">На главную!</a>');
    27.     }
    28. ?>
     
  19. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.861
    Симпатии:
    657
    Попробуйте при входе использовать пароль $pwd (4 символа) ;)
    --- Добавлено ---
    Логика добавления неправильная. Так с БД обычно не работают. Нужно сделать мыло первичным ключом или юником и делать вставку без предварительной выборки, а потом уже смотреть на результат.
     
  20. evkon

    evkon Новичок

    С нами с:
    22 ноя 2016
    Сообщения:
    7
    Симпатии:
    0
    Можно поподробнее, я не совсем понял. Пароль у меня генерируется через класс, на выходе 8 символов, его хеш заносится в таблицу, пароль отправляется на email, с ним я и пытаюсь войти. На какой стадии мне нужно использовать $pwd (4 символа)? У меня id первичный ключ, так не очень? Как вставка может предшествовать выборке, нам же email нужно проверить на наличие его в таблице, я совсем запутался.
     
  21. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.861
    Симпатии:
    657
    Я имел в виду, что вам нужно попробовать ввести при входе в качестве пароля $pwd (для любого пользователя) – думаю, будете сильно удивлены :)

    Если первичный ключ другой, используйте юник (уникальный индекс).
     
    denis01 нравится это.
  22. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.861
    Симпатии:
    657
    P.S. Если мыло будет уником, то сервер БД будет сам проверять при вставке, чтобы не было совпадений.
     
  23. evkon

    evkon Новичок

    С нами с:
    22 ноя 2016
    Сообщения:
    7
    Симпатии:
    0
    Всё, теперь дошло. Убрал кавычки. Моя самая большая ошибка в том, что шех от этих четырёх символов $pwd я принял за шех от значения переменной $pwd и думал, что в таблице у меня лежит шех пароля. Спасибо вам большое.

    По поводу уникальности email тоже понял. Здесь нужно обрабатывать исключение через try catch или if (mysqli) хватит?
    А я только с num_rows научился работать :D Вообще, с помощью форума код стал короче, что не может не радовать.
     
  24. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.861
    Симпатии:
    657
    Хватит if. Посмотрите, что возвращает query для таких запросов, как INSERT.
    --- Добавлено ---
    Пока не вижу, как это можно использовать. Я вам на киберфоруме показал, что для определения наличия строки в результате выборки это абсолютно лишнее.
     
  25. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Один мальчик любил фреймфорки, кроссплатформенность, абстракции и оверхеды, другой же любил экономить, монолиты и был уверен, что вся эта новомодная хрень ни кому не нужна. Когда же бутылочным горлышком оказались не эти-ваши-фреймворки, а отсутствие даже теоретической возможности нормально масштабироваться, свои, домашние решения начали выдавать непредвиденные глюки, согласно фазе Луны, первому мальчику поручили все это разгребать. Дык вот, с тех пор он люто шлет лучи ненависти всем, кто вместо того, что бы прививать новичкам нормальные подходы лезет со своими нужно-не-нужно. Ушел.