【问题标题】:password_verify returns false. cant find error [duplicate]password_verify 返回 false。找不到错误[重复]
【发布时间】:2019-05-18 11:12:57
【问题描述】:

我已经尝试解决这个问题大约 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();
?>

【问题讨论】:

  • 缩进。您认为将用户密码作为 URL 的一部分进行设计是一种好的设计吗?
  • @miken32 我目前正在使用 get 以确保系统能够正常工作,然后将切换到 post。
  • 以你想要完成的方式开始。如果您希望任何人查看它,您需要正确格式化您的代码。我还建议添加存储哈希的代码,并确保您清除数据库以进行测试。

标签: php passwords password-protection password-encryption password-hash


【解决方案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();
?>

这里我稍作修改,并在代码中添加了一些 cmets,以帮助您理解该方法。

<?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();
?>

【讨论】:

  • 修改后的代码可以用硬编码的密码找到,但是一旦我将它连接到数据库并尝试它,密码验证失败。
  • @MineCakePvP - 听起来存储的哈希是问题所在。您是否检查过您使用varchar(255) 来存储哈希?还要检查使用password_hash() 是否正确生成了哈希,通常一些不可见的字符(如换行符)是问题所在。
  • @martinstoeckli 是对的,你也可以在你的数据库中尝试这个工作哈希!替换您的哈希并粘贴此哈希,如果它不起作用,则表示您没有正确阅读此字段,请确保在比较时不要使用 mysqli_real_escape_string。
  • @antoni 我确保使用 password_hash() 对密码进行哈希处理,并确保该表使用长度为 255 的 varchar,但它仍然无法正常工作。
  • 你应该读取你的数据库哈希,然后die(print_r(['your_hardcoded_password', $db_password, password_verify('your_hardcoded_password', $db_password)], true));你能告诉我结果吗?
猜你喜欢
  • 1970-01-01
  • 2021-07-11
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
  • 1970-01-01
  • 1970-01-01
  • 2014-03-11
相关资源
最近更新 更多