简体   繁体   English

针对MySQL的password_verify()无法正常工作

[英]password_verify() against MySQL doesn't work

I store the password, get through a form, into MySQL database via PDO, after having hashed it with password_hash() (VARCHAR(512) field) 在使用password_hash()(VARCHAR(512)字段)对密码进行哈希处理之后,我将密码通过表单存储到MySQL数据库中。

$options = array(
    'cost' => 12
);
$password = password_hash($password, PASSWORD_BCRYPT, $options);

Suppose that 假设

$pass = "123Azerty";
//and the hash is
$hash = "$2y$12$TzpGzy1cKM81pkEr/Mn0SOVA4wn0lr.7PnKFg4SU9Hto0EUiGGRMe";

When I get the password from the database and I verify it with password_verify() it returns always false 当我从数据库获取密码并使用password_verify()进行验证时,它始终返回false

...
...
$returnedPWD = $row['password'];
if (password_verify($pass,$returnedPWD)){
    echo "TRUE";
} else {
    echo "FALSE";
}
...
...

At this point, I tried to do it "manually" in this way 在这一点上,我尝试以这种方式“手动”进行操作

$pass = "123Azerty";
$hash = "$2y$12$TzpGzy1cKM81pkEr/Mn0SOVA4wn0lr.7PnKFg4SU9Hto0EUiGGRMe";
if (password_verify($pass,$hash )){
    echo "TRUE";
} else {
    echo "FALSE";
}

And it always returned FALSE 它总是返回FALSE

BUT

when I changed 当我改变

$hash = "$2y$12$TzpGzy1cKM81pkEr/Mn0SOVA4wn0lr.7PnKFg4SU9Hto0EUiGGRMe";
// into
$hash = '$2y$12$TzpGzy1cKM81pkEr/Mn0SOVA4wn0lr.7PnKFg4SU9Hto0EUiGGRMe';

it worked. 有效。 Because the hash enclosed in single quotes, is not parsable. 因为用单引号引起来的哈希是不可解析的。 On my understanding, it means that the hash taken from database, it is interpreted as parsable (double totes) than it doesn't work at all 以我的理解,这意味着从数据库中获取的哈希被解释为可解析的(双重搬运),而不是根本无法工作

then I tried to enclose the string out the db int strval(): 然后我尝试将字符串括在db int strval()中:

...
...
$returnedPWD = strval($row['password']);
if (password_verify($pass,$returnedPWD)){
    echo "TRUE";
} else {
    echo "FALSE";
}
...
...

But it returns always FALSE reading all the posts related the not functioning of password_verify(), I didn't come up to any valid solution, for me. 但是它总是返回FALSE,阅读所有与password_verify()无法正常运行有关的帖子,对我而言,我没有提出任何有效的解决方案。

Please is there a way to make it work? 请问有什么方法可以使它起作用吗?

Thanks in advance 提前致谢

EDIT 1 编辑1

I did try with other settings as PASSWORD_DEFAULT but no changes. 我确实尝试了其他设置,如PASSWORD_DEFAULT,但没有任何更改。 I also tried to base64 encode it upfront database storage, then decode it. 我还尝试对前期数据库存储进行base64编码,然后对其进行解码。 But nothing changed 但是什么都没有改变

EDIT 2 编辑2

I store the data using PDO with parameters 我使用带有参数的PDO存储数据

 $query = "INSERT INTO `users` (username, password) VALUES (:username, :password)";

 $params = array(
            ':username' => "$username",
            ':password' => "$password" // hashed one
        );

EDIT 3 编辑3

Table Structure 表结构

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `password` varchar(512) NOT NULL,
  `enabled` int(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=13 ;


$username = trim($_POST["username"];
$password = trim($_POST["password"];

// Query to insert data
 $query = "INSERT INTO `users` (username, password, enabled) VALUES (:username, :password, 1)";

// The very original setup I did use and didn't work out
$param_password = password_hash($password, PASSWORD_DEFAULT); 

// Bind parameters
$params = array(
     ':username' => "$username",
     ':password' => "$param_password"
);
...
...
// insert into db
$sth = $sql->prepare($query);

// Call MySQL
try {
    $sth->execute($params); // Execute the Query
} catch (PDOException $e) {
    $mysql_error = 'MySQL connection failed: ' . "<br>" . $e->getMessage();
}
...
...

and here the fundamental lines on how I read from database 这里是我如何从数据库读取的基本内容

...
...
$username_login = trim($_POST["username"]);
$password_login = trim($_POST["password"]);
...
...   
$query = "SELECT * FROM `users` WHERE username = :username";
$params = array(
    ':username' => $username_login
);   

$sth = $sql->prepare($query);

try{
    $sth->execute($params);
} catch (PDOException $e)  {
    $mysql_error = 'MySQL connection failed: ' . "<br>" . $e->getMessage();
}

while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
    foreach ($row as $key => $value) {
        global $$key;
        $$key = $value;
    }
}
...
...

if (password_verify($password_login, $password) and $enabled == 1){
    // Password is correct, so start a new session
    session_start();

    // Store data in session variables
    $_SESSION["logged"] = true;
    $_SESSION["id"] = $id;
    $_SESSION["uname"] = $username_login_;                            

    // Redirect user to welcome page
    header("location: index.php");

} else {
    // Display an error message if password is not valid
    $password_login__err = "The password you entered was not valid. Or you are not enabled";
}
...
...

Your code does not work because of "$password " - it has space at the end. 您的代码由于"$password "而无法工作-它的末尾有空格。 It should be: 它应该是:

$query = "INSERT INTO `users` (username, password) VALUES (:username, :password)";

$params = array(
        ':username' => $username,
        ':password' => $password, // hashed one
    );

Your manual test does not work because 您的手动测试无效,因为

$hash = "$2y$12$TzpGzy1cKM81pkEr/Mn0SOVA4wn0lr.7PnKFg4SU9Hto0EUiGGRMe";

has double quotes and it interpolates $2y , $12 and $Tz... as variables that leads to empty string. 有双引号,并且将$2y$12$Tz...内插$2y导致空字符串的变量。 That's why single quotes works. 这就是单引号起作用的原因。


From your provided information I constructed sample code that does work: Check here 根据您提供的信息,我构建了有效的示例代码: 在此处检查

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM