password_verify возвращает false с правильным паролем

Поэтому я пытаюсь проверить хешированный пароль пользователя из БД MySQL, но password_verify не похоже на работу. Я чувствую, что, может быть, я что-то не так делаю.

Хеширование и хранение пароля:

// Set POST variables
$firstname = mysqli_real_escape_string($conn, $_POST['firstname']);
$lastname = mysqli_real_escape_string($conn, $_POST['lastname']);
$email = mysqli_real_escape_string($conn, $_POST['email']);
$password = mysqli_real_escape_string($conn, $_POST['password']);
$hashedpwd = password_hash($password, PASSWORD_DEFAULT);

// SQL query & Error Handlers
$sql = "INSERT INTO `users_admin` (Firstname, Lastname, Email, Password) VALUES ('$firstname', '$lastname', '$email', '$hashedpwd')";

Восстановление хешированного пароля:

 if ($row = mysqli_fetch_assoc($result)) {
        $user_pass = $row['Password'];
        $passwordCheck = password_verify($password, $user_pass);
        if (!$passwordCheck) {
            header("Location: ../login.php?wrong-password");
            exit();
        } elseif ($passwordCheck) {
            // log in the user
            $_SESSION['logged_in'] = true;
            $_SESSION['id'] = $row['ID'];
            $_SESSION['firstname'] = $row['Firstname'];
            $_SESSION['lastname'] = $row['Lastname'];
            $_SESSION['email'] = $row['Email'];
            header("Location: ../dashboard");
            exit();

        }
    }

password_verify = bool(true)

РЕДАКТИРОВАТЬ:

if (isset($_POST['submit'])) {

include('DB_Connect.php');

$email = mysqli_real_escape_string($conn, $_POST['email']);
$password = mysqli_real_escape_string($conn, $_POST['password']);

// error handlers
$sql = "SELECT * FROM users_admin WHERE Email = '$email'";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
if ($resultCheck < 1) {
    header("Location: ../login.php?input:invalid");
    exit();
} else {
    if ($row = mysqli_fetch_assoc($result)) {
        $user_pass = $row['Password'];
        $passwordCheck = password_verify($password, $user_pass);
        if (!$passwordCheck) {
            header("Location: ../login.php?wrong-password");
            exit();
        } elseif ($passwordCheck) {
            // log in the user
            $_SESSION['logged_in'] = true;
            $_SESSION['id'] = $row['ID'];
            $_SESSION['firstname'] = $row['Firstname'];
            $_SESSION['lastname'] = $row['Lastname'];
            $_SESSION['email'] = $row['Email'];
            header("Location: ../dashboard");
            exit();

         }
     }
  }
}else{
    header("Location: ../login.php?login=error");
    exit();
}

2 ответа

В опубликованном вами коде нет ничего, что могло бы привести к описанной проблеме.

Вот несколько советов и улучшений:

1.

Вы экранируете / исправляете пароль перед его хэшированием.

Таким образом, вы изменяете сохраненный пароль

Позволять

$password = $_POST['password'];

как при создании учетной записи, так и при проверке совпадения пароля при входе в систему.

2.

Убедитесь, что Password Поле в базе данных (в котором хранится хешированный пароль) способно хранить до 255 символов.

Из документации

Рекомендуется сохранить результат в столбце базы данных, который может быть расширен за пределы 60 символов (было бы неплохо выбрать 255 символов).

Если поле будет уже, хэш будет обрезан, и совпадения никогда не будет.

3.

Получив пользователя по электронной почте при входе в систему, убедитесь, что Email уникален (если ваш первичный ключ ID) на уровне базы данных (в определении таблицы).

Хорошая идея проверить это также при регистрации пользователя и входе в систему (на уровне php).

4.

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

Ex. в вашем коде я читаю $row['Email'], В таблице есть имя поля на самом деле Email или, может быть, это email (строчные)?

5.

Отладка вашего кода!

Используйте отладчик или просто установите точку останова, например

var_export( $the_variable );
exit();

в "ключевых" точках вашего кода.

6.

Используйте подготовленные операторы вместо экранирования ввода и внедрения его непосредственно в строки SQL.


Хеширование и хранение пароля:

// Set POST variables
$firstname = mysqli_real_escape_string($conn, $_POST['firstname']);
$lastname = mysqli_real_escape_string($conn, $_POST['lastname']);
$email = mysqli_real_escape_string($conn, $_POST['email']);
$password = $_POST['password'];
$hashedpwd = password_hash($password, PASSWORD_DEFAULT);

// SQL query & Error Handlers
$sql = "INSERT INTO `users_admin` (Firstname, Lastname, Email, Password) VALUES ('$firstname', '$lastname', '$email', '$hashedpwd')";

Восстановление хешированного пароля:

include('DB_Connect.php');

$email = mysqli_real_escape_string($conn, $_POST['email']);
$password = $_POST['password'];

$sql = "SELECT * FROM users_admin WHERE Email = '$email'";
$result = mysqli_query($conn, $sql);

if( $result === false )
{
    header("Location: ../login.php?login=error");
    exit();
}

$count = mysqli_num_rows($result);
if( $count === 0 )
{
    header("Location: ../login.php?input:invalid");
    exit();
}

$row = mysqli_fetch_assoc( $result );

$passwordHash = $row['Password'];
$passwordCheck = password_verify( $password, $passwordHash );
if( ! $passwordCheck )
{
    header("Location: ../login.php?wrong-password");
    exit();
}

// log in the user
$_SESSION['logged_in'] = true;
$_SESSION['id'] = $row['ID'];
$_SESSION['firstname'] = $row['Firstname'];
$_SESSION['lastname'] = $row['Lastname'];
$_SESSION['email'] = $row['Email'];
header("Location: ../dashboard");
exit();

Паоло отвечает хорошо и отвечает на ваш вопрос, я просто хотел объяснить вам, почему ваши пароли не совпадают.

Сначала вы берете POST-пароль и экранируете его:

$password = mysqli_real_escape_string($conn, $_POST['password']);

И тогда вы хэшируете пароль:

$hashedpwd = password_hash($password, PASSWORD_DEFAULT);

Но здесь:

$passwordCheck = password_verify($password, $user_pass);

Вы password_verify неэкранированный пароль (я предполагаю, что вы не опубликовали полный код)

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

Другие вопросы по тегам