我试图了解有关PHP安全最佳实践的更多信息,我遇到了Anthony_hash和Anthony Ferrara的password_compat项目。我想我理解如何实现它,但在测试中,我遇到了一个奇怪的行为,这与我对密码散列的新手理解相矛盾。
如果我将password_hash函数的结果保存到MySQL数据库用户记录中,然后使用password_verify检索该哈希以进行验证,则它会按预期工作。但是,如果我做了完全相同的事情,而不是从数据库中提取,我只是通过数据库中的复制/粘贴来硬编码密码哈希,password_verify函数失败。
代码如下:
// Get the Username and password hash from the MySQL database. GetPassTestuser routine returns an array where
// position[0][0] is the username and position[0][1] is the password hash.
$arrUser = GetPassTestuser("mike24");
echo("User Name: ".$arrUser[0][0]."<br/>");
echo("Password hash: ".$arrUser[0][1]."<br/>");
// Run password_verify with the password hash collected from the database. Compare it with the string "mytest"
// (This returns true in my tests).
if (password_verify("mytest",$arrUser[0][1])){
echo("Password verified");
} else {
echo("Password invalid");
}
echo("<hr>Now On to our second test...<br/>");
// Now run password_verify with a string representation directly copied/pasted from the database. This is
// being compared with "mytest", which in my mind should return a true value. But it doesn't and this test
// fails. Not sure why.
if (password_verify("mytest","$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm")){ // String shown here is the same as value contained in $arrUser[0][1]
echo("2nd Test Password verified");
} else {
echo("2nd test Password invalid");
}
虽然这不是我在实际代码中所做的事情,但我只想了解其中的区别。当我使用可能包含完全相同的哈希值的字符串变量时,为什么它可以正常工作,但是当它被硬编码时不起作用?
谢谢!
答案 0 :(得分:5)
来自PHP DOC
要指定文字单引号,请使用反斜杠()对其进行转义。要指定文字反斜杠,请将其加倍(\)。反斜杠的所有其他实例将被视为文字反斜杠:这意味着您可能习惯使用的其他转义序列(如\ r或\ n)将按字母顺序输出,而不是具有任何特殊含义。
如果遇到美元符号($),解析器将贪婪地获取尽可能多的令牌以形成有效的变量名称。将变量名括在花括号中,以明确指定名称的结尾。
使用单引号
替换
"$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm"
用
'$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm'
或者
"\$2y\$10\$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm"
答案 1 :(得分:2)
关于我的评论,我认为这可以更好地作为答案:
if (password_verify("mytest",'$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm')){ // String shown here is the same as value contained in $arrUser[0][1]
echo("2nd Test Password verified");
} else {
echo("2nd test Password invalid");
}
答案 2 :(得分:1)
查看PHP手册中的Strings章节。简而言之,您的硬编码哈希是一个带有可变插值的PHP字符串:
"$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm"
^ ^ ^
由于这些变量不存在,您最终会得到三个空白子串。你应该看到通知。如果没有,请检查错误报告设置。
(提示:除了你想要进行变量插值的地方外,在任何地方都使用单引号。)