【问题标题】:PHP password_hash and password_verify Not Working with MySQLPHP password_hash 和 password_verify 不适用于 MySQL
【发布时间】:2015-02-23 03:43:14
【问题描述】:

我正在使用password_hash 将密码存储在 VARCHAR(255) 类型的 MySQL 数据库字段中。当我尝试登录用户并验证凭据时,password_verify 函数总是返回 false。

这是将密码存储在 MySQL 数据库中的代码摘录:

$password_hash = password_hash($password, PASSWORD_DEFAULT);

// Generate API Key
$api_key = $this->generateApiKey();

// Insert Query
$stmt = $this->conn->prepare("INSERT INTO user(email, password, name, api_key, status) values(?, ?, ?, ?, 1)");
$stmt->bind_param("ssss", $email, $password_hash, $name, $api_key);
$result = $stmt->execute();
$stmt->close();

还有检查密码的代码:

// Query user by email
$stmt = $this->conn->prepare("SELECT password FROM user WHERE email = ?");
$stmt->bind_param("s", $email);
$stmt->execute();

$stmt->bind_result($password_hash);
$stmt->store_result();

if ($stmt->num_rows > 0) {
    // Found user with that email address
    // Now verify the password

    $stmt->fetch();
    $stmt->close();

    if (password_verify($password, $password_hash)) {
        // User password is correct
        return TRUE;

然后我写了这个测试代码并直接从 MySQL 字段中获取数据,但仍然失败。当我在同一个文件(下面文件中的 $hash2 )中创建 password_hash 时 - 然后密码验证正确。

$password = 'pass1234567890';
$hash = '$2y$10$JLP/pPei6RYRdUmoH8H5RO7iJyImOtrBLsrRRfq3XpeqNE3lQ/l7O';
$hash2 = password_hash($password, PASSWORD_DEFAULT);

echo $hash . " - " . strlen($hash);
echo "<br />";
echo $hash2 . " - " . strlen($hash2);
echo "<br />";

if (password_verify($password, $hash)) {
    echo "Password Valid!";
} else {
    echo "Password invalid!";
}

echo "<br /><br />";

if (password_verify($password, $hash2)) {
    echo "Password 2 Valid!";
} else {
    echo "Password 2 invalid!";
}

【问题讨论】:

  • 你确定这是正确的哈希吗?
  • 我直接从数据库中获取了该字段,尽管我确实注意到每次刷新测试页面时 $hash2 变量都会发生变化,但我不能 100% 确定 crypt 的工作原理以完全理解原因。
  • 检查你的 MySQL 字符编码;检查您的数据库编码,检查您的表编码并检查您的列编码和排序规则。 MySQL should be using UTF8mb4_ character sets and collations.
  • 还有;注意;成本 = 10 太低了。您的服务器的成本价值应尽可能高;通常 14+

标签: php mysql password-hash


【解决方案1】:

这证明你的哈希有问题

<?php
// See the password_hash() example to see where this came from.
$password = 'pass1234567890';
$hash = '$2y$10$JLP/pPei6RYRdUmoH8H5RO7iJyImOtrBLsrRRfq3XpeqNE3lQ/l7O';

$hash2 = '$2y$10$gMJKYZUc1FKSZBnsONxLOebOHj.uuEWSiCP0jo4Zv0iAHBz6iz.NG';

if (password_verify('pass1234567890', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}

echo "<br>";

if (password_verify('pass1234567890', $hash2)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}

截图

【讨论】:

  • 明白,但password_verify 应该能够验证由该密码生成的任何哈希值是否正确?
  • @mattdonders 我觉得那个哈希有问题。我创建了一个新的哈希,我的作品完美无缺。尝试使用我的哈希更新记录(如果我的示例对您不利),如果您得到其他信息,请告诉我。
  • 但是有什么问题呢?哈希的长度相同,我也在使用bind_param() 对 VARCHAR(255) 进行 INSERT。该测试文件中的 $hash 直接来自数据库。
  • 所以你是说,手动删除用户,重新创建他们,然后再试一次?
  • 可能是你设置密码的时候多了个字符?空间或可以是许多其他的东西
【解决方案2】:

在我的情况下,问题是我将数据库连接查询存储在另一个文件中,其中包含用于获取当前密码的相同变量,所以发生的情况是首先我将变量“密码”分配给当前密码,然后包括我的连接查询文件,它具有相同的变量“密码”,因此发生的事情是,注册表单的“密码”变量被连接查询的“密码”变量重新分配,这就是它实际上散列另一个密码的原因。所以通过改变变量名这个问题就解决了。

这是我的参考代码,

注册.php

    $email = $_POST["email"];
    $password = $_POST["password"];
    
    include 'partials/php/_dbconnect.php';
    $passwordHash = password_hash($passwd, PASSWORD_DEFAULT);

_dbconnect.php

<?php
$server = "localhost";
$username = "root";
$password = "";
$database = "demo";

$connectionquery = mysqli_connect($server, $username, $password, $database);
?>

我改成了;

    $email = $_POST["email"];
    $passwd = $_POST["password"];
    
    include 'partials/php/_dbconnect.php';
    $passwordHash = password_hash($passwd, PASSWORD_DEFAULT);

【讨论】:

    【解决方案3】:
    password_verify($password,trim($password_hash)))
    

    虽然我不确定它是在存储哈希时还是在检索期间发生的,但 password_hash 末尾有一个空格。在将哈希提供给 password_verify 之前修剪哈希为我解决了这个问题。

    【讨论】:

      【解决方案4】:

      只需为if(password_verify($pass_input, $pass_db)) 创建一个变量 其中$pass_input 是文本形式给出的值,$pass_db 是存储在 mysql 中的值(散列)

      像这样:

      $verif_pass = (password_verify($pass_input, $pass_db));
      if($verif_pass){echo "TRUE"} else {echo "FALSE";}
      

      只需根据需要修改 TRUE/FALSE。

      【讨论】:

      • 你能进一步解释一下吗?为什么要添加一个新变量来解决问题?
      • 不确定……如果匹配,password_verify 返回一个布尔值 TRUE,如果失败,则返回 FALSE。但脚本工作正常。
      • 我只是在没有为它创建变量的情况下尝试过并且可以正常工作,这样的脚本.. if(password_verify($pass_input, $pass_db) === TRUE ){echo "TRUE";} else {回声“假”;}
      • 与给定的代码相比,究竟有什么变化?它只打印其他东西吗?或者您认为额外检查=== TRUE 有什么不同?请编辑您的答案以包含所有此类信息 - 请记住,其他人应该能够从中学习
      • 请编辑您的答案以包含所有信息 - 毕竟给定的答案不包含password_hash
      猜你喜欢
      • 2022-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-30
      • 2013-02-06
      • 2015-05-10
      相关资源
      最近更新 更多