如果我从db获取哈希值,则password_verify返回false,但如果我复制并粘贴它,则返回true

时间:2018-02-03 04:20:21

标签: php mysql pdo hash bcrypt

将密码放入我的数据库后 (列密码是二进制(255)类型)

//let's say his username is on $username and password in $password
$password = "abc123";
$con = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$con->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$sql = "INSERT INTO users(username, password) VALUES(:usr,:psw)";
$stmt->bindValue( "usr", $username, PDO::PARAM_STR );
$newpsw = password_hash ( $password , PASSWORD_DEFAULT);
$stmt->bindValue( "psw", $newpsw, PDO::PARAM_STR );
$stmt->execute();

通过cmd我去数据库,我可以看到密码是这个

$2y$10$nDzlRwWfC9sTvVqv5f7G1eByHethRHjEWGwBOjkpoaq3y2Fb.LCC.

现在,当用户登录时,我成功地从数据库中检索了他的密码

//let's say his username is on $username and password in $password
$con = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$con->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$sql = "SELECT password FROM users WHERE username = :usr LIMIT 1";
$stmt = $con->prepare( $sql );
$stmt->bindValue( "usr", $username, PDO::PARAM_STR );
$stmt->execute();
$result = $stmt->fetch();
$psw_from_db = $result["password"]; //checked with echo and it's correct

如果我这样做

password_verify($password , $psw_from_db);

虽然我检查了$ password和$ psw_from_db,但它会返回false 并且他们内部有正确的价值。

如果我直接从数据库中复制密码并将其替换为$ psw_from_db,则会返回true

password_verify($password ,'$2y$10$nDzlRwWfC9sTvVqv5f7G1eByHethRHjEWGwBOjkpoaq3y2Fb.LCC.');
//'' have to be used, it won't work with ""

我现在正在寻找几个小时,但我还没有找到解决方案。

1 个答案:

答案 0 :(得分:3)

根据BINARY datatype in MySQL的文档,您看到的答案似乎是\0(空字符):

  

当存储BINARY值时,它们会用填充板右边填充   值到指定的长度。填充值为0x00(零   字节)。值在插入时右边填充0x00,没有尾随   select上删除了字节。所有字节在比较中都很重要,   包括ORDER BY和DISTINCT操作。 0x00个字节和空格   比较不同,0x00<空间。

因此,当您从数据库中检索密码时,您实际上收到的长度为255的字符串(这就是我在my comment中要求var_dump而不是echo)的原因。在本地测试一些值,我得到了类似的东西:

string(255) "$2y$10$L5C66A5xFvf1YYAoWbnQDuRyveVOrnz1jfV/Eb0kT9UkZlWzCfK8a"
string(255) "$2y$10$EAkfkh8S1m66FWAX/KZYMeuhteDREL5B22cgLP0feKZ9.ydMgcgpa"
string(255) "$2y$10$Ll/272JbvIilDj74FAqVIeckWUGezqT926Z1LkVBZZSVwTaFUGOLe"
string(255) "$2y$10$fxvZv2ya0RncOksp09vqjekIWNmdEX9fEUahU6puSe8HqGcY51re6"
string(255) "$2y$10$f1xDu3fFnqMw.MEa4.93Tu3ouhr3kmXXbe41oTyy8xGTKaRbafQ8G"
string(255) "$2y$10$YhjBmNFjL7a8lj1Soyvdhe9GpfQ7SsX.dfkI0keQ0IgrkKIfQQjpC"

您可以使用trim或使用BINARY(255)归类将数据类型从BINARY(60)更改为CHAR(60) BINARYCHAR(60),甚至更改为latin1。 (bcrypt哈希值为59-60字节)。