password_verify возвращает false. не могу найти ошибку

Я пытался решить эту проблему около 2 месяцев и, похоже, не могу ее понять. У меня есть база данных, которая возвращает хешированный пароль. Я могу подтвердить, что это работает, распечатав всю информацию. Он может возвращать нехешированный и хешированный пароль совершенно нормально, но когда он проверяет пароль, он всегда возвращает false.

Я не уверен что делать. Это может быть что-то действительно легкое, но я, кажется, не могу этого найти.

<?php
    session_start();
    $dbip = "localhost";
    $dbuser = "root";
    $dbpass = "";
    $dbname = "projectNitro";
    $conn = new mysqli($dbip, $dbuser, $dbpass, $dbname);

    if($conn->connect_error) {
        echo("Connection failed: " . $conn->connect_error);
    }

    $password = mysqli_real_escape_string($conn, $_GET["pass"]);
    $email = mysqli_real_escape_string($conn, $_GET["email"]);
    $sql = "SELECT * FROM users WHERE email='{$email}' LIMIT 1";
    $query = mysqli_query($conn, $sql);
    $pass = $_GET["pass"];

    if($query == TRUE) {
        $row = mysqli_fetch_array($query);
        $db_password = $row['password'];
        $db_usertype = $row['accountType'];
        $username = $row['username'];
        echo $password;
        echo "<br>";
        echo $db_password;
        echo "<br>";
        $verify = password_verify($pass, $db_password);

        if($verify) {
            $_SESSION['username'] = $username;
            $_SESSION['at'] = $db_usertype;
            header("Location: http://website.com");
        } else {    
            echo("DB Email: "
            .$row["email"]
            ."<br>Username: "
            .$row["username"]
            ."<br>DB Password: "
            .$row["password"]
            ."<br>AccountType: "
            .$row["accountType"]
            ."<br>Inserted Email: "
            .$_GET["email"]
            ."<br>Inserted Password: "
            .$_GET["pass"]."<br>");

            if(password_verify($_GET["pass"], $row["password"])) {
                echo("epic<br>");
            } else {
                echo("not epic<br>");
            }
        }
    } else {
        header("Location: http://website.com");
    }
    $conn->close();
?>

person MineCake PvP    schedule 18.12.2018    source источник
comment
INDENT. Считаете ли вы, что пароли пользователей как часть URL-адреса - это хороший дизайн?   -  person miken32    schedule 18.12.2018
comment
@ miken32 В настоящее время я использую get, чтобы убедиться, что система работает, а затем переключусь на публикацию.   -  person MineCake PvP    schedule 18.12.2018
comment
Начни так, как хочешь закончить. Вам необходимо правильно отформатировать свой код, если вы хотите, чтобы кто-нибудь его посмотрел. Я также предлагаю добавить код, в котором хранится хэш, и убедиться, что вы стерли свою базу данных в целях тестирования.   -  person miken32    schedule 18.12.2018


Ответы (1)


Вам нужно делать маленькие шажки. продолжайте увеличивать, пока это работает.

Вот более простая версия вашего кода, которая должна работать с образцом пароля из официального документа: http://php.net/manual/en/function.password-verify.php

Также используйте die(); для отладки вашего кода в каждом {} блоке. В вашем текущем коде вы перенаправляете на веб-сайт, и в обоих случаях очень сложно отследить, что не так, если вас перенаправляют!

У вас есть бесполезные и неясные переменные, например $dbpass, $db_password очень неоднозначны, даже если мы с вами понимаем, что это делает их не обслуживаемыми. Помимо вашего стиля кодирования, вам нужно делать отступы!

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

<?php

session_start();
$dbip = "localhost";
$dbuser = "root";
$dbpass = "";
$dbname = "projectNitro";
$conn = new mysqli($dbip, $dbuser, $dbpass, $dbname);

if ($conn->connect_error){
  echo("Connection failed: " . $conn->connect_error) . '<br><br>';
}

$password = 'rasmuslerdorf';//mysqli_real_escape_string($conn, $_GET["pass"]);
// $email = mysqli_real_escape_string($conn, $_GET["email"]);
// $sql = "SELECT * FROM users WHERE email='{$email}' LIMIT 1";
// $query = mysqli_query($conn, $sql);
// $pass = $_GET["pass"];

// if ($query == TRUE) {
  // $row = mysqli_fetch_array($query);
  $db_password = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';
  // $username = $row['username'];

  echo $password;
  echo "<br>";
  echo $db_password;
  echo "<br>";

  if (password_verify($password, $db_password)) {
    die('ok');
  } else {
    die('not ok');
  }
// } else {
//   header("Location: http://website.com");
// }

$conn->close();
?>

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

<?php

session_start();

// This array is used only like a simple namespace.
$dbCredentials = [
  'host' => "localhost",
  'user' => "root",
  'password' => "",
  'dbname' => "projectNitro"
];
$dbConn = new mysqli($dbCredentials['host'], $dbCredentials['user'], $dbCredentials['password'], $dbCredentials['dbname']);

if ($dbConn->connect_error) {
  // Should not continue script if can't connect to DB.
  die("Connection failed: " . $dbConn->dbConnect_error);
}

// You should check the existence of $_GET["pass"] before using it, with empty() or isset().
$passwordToCheck = mysqli_real_escape_string($dbConn, $_GET["pass"]);// Renamed var more meaningful.
$userEmail = mysqli_real_escape_string($dbConn, $_GET["email"]);
$sql = "SELECT * FROM users WHERE email='{$userEmail}' LIMIT 1";// Don't select * if you don't need everything.
$query = mysqli_query($dbConn, $sql);
$pass = $_GET["pass"];// you already have $passwordToCheck.

if ($query) {// Don't need == TRUE
  // $row = mysqli_fetch_array($query);
  $db_password = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';
  $username = $row['username'];

  echo "$passwordToCheck<br>$db_password<br>";// This is way less verbose than repeating echo and uses less echo functions.

  if (password_verify($passwordToCheck, $db_password)) {// Don't need to keep this condition in a variable. 
    die('ok');// this is just an example to test.
  } else {
    die('not ok');// this is just an example to test.
  }
} else {
  header("Location: http://website.com");// While debugging don't redirect, put die('message');
}

$dbConn->close();
?>
person antoni    schedule 18.12.2018
comment
Модифицированный код работает с жестко запрограммированным паролем, но как только я подключаю его к базе данных и пробую, пароль не удается проверить. - person MineCake PvP; 18.12.2018
comment
@MineCakePvP - Похоже, проблема в хранящемся хеш-коде. Вы проверили, что вы использовали varchar(255) для хранения хэша? Также проверьте, что хеш сгенерирован правильно с password_hash(), часто проблема возникает из-за невидимых символов, таких как новые строки. - person martinstoeckli; 19.12.2018
comment
@martinstoeckli прав, и вы также можете попробовать этот рабочий хеш в своей базе данных! Замените свой хеш и вставьте его вместо него, если он не работает, это означает, что вы не читаете это поле должным образом, убедитесь, что не mysqli_real_escape_string его при сравнении. - person antoni; 20.12.2018
comment
@antoni Я убедился, что пароль хеширован с помощью password_hash (), и убедился, что в таблице используется varchar длиной 255, и он по-прежнему не работает. - person MineCake PvP; 24.12.2018
comment
Вы должны прочитать хэш своей базы данных, тогда die(print_r(['your_hardcoded_password', $db_password, password_verify('your_hardcoded_password', $db_password)], true)); можете ли вы сказать мне результат? - person antoni; 24.12.2018