[英]When do I need to use password_needs_rehash()?
I have a processing file for a login to an app.我有一个用于登录应用程序的处理文件。 I either do not understand the purpose of
password_needs_rehash()
or it is not working.我要么不明白
password_needs_rehash()
的用途,要么它不起作用。 The login is authenticating and passing me through to the correct page.登录正在验证并将我传递到正确的页面。 But I can't get the code to even echo the new hash.
但我什至无法获得代码来回应新的 hash。
Am I doing this correctly?我这样做正确吗?
Does the if
not throw a new hash because it does not need rehashed? if
不抛出一个新的 hash 是因为它不需要重新散列吗? If so when would a password need rehashed if it was properly hashed and stored in the DB?如果是这样,如果密码被正确散列并存储在数据库中,什么时候需要重新散列密码?
My processing file is below:我的处理文件如下:
$hash = $row['hash'];
$userPassword = $_POST["li_password"];
if (password_verify($userPassword, $hash)) {
if ( password_needs_rehash($hash, PASSWORD_DEFAULT, ['cost' => 12]) ) {
$newhash = password_hash($userPassword, PASSWORD_DEFAULT, ['cost' => 12]);
echo $newhash;
}
} else {
header('Location: http://' . $_SERVER['HTTP_HOST'] . '?error=loginfailed');
exit();
}
The function password_needs_rehash()
only needs to be used if you change the $options
which usually refers to the cost
.函数
password_needs_rehash()
仅在您更改通常指的是cost
的$options
时才需要使用。
The more the cost, the more CPU time it takes to hash the password but the more difficult it becomes to crack it.成本越高,散列密码所需的 CPU 时间就越多,但破解密码的难度就越大。 If you change hosting or move over to a cloud based system where multiple computers can calculate the hash for you, you are able to increment it at your own discretion.
如果您更改托管或转移到基于云的系统,其中多台计算机可以为您计算散列,您可以自行决定增加它。
You only need to check if the password needs a rehash at user login, since password_verify()
can still verify the password if you changed the $options
.您只需要在用户登录时检查密码是否需要重新哈希,因为如果您更改了
$options
, password_verify()
仍然可以验证密码。 If password_needs_rehash()
returns true at that point, use password_hash()
with the new options and replace the old hash.如果此时
password_needs_rehash()
返回 true,请使用带有新选项的password_hash()
并替换旧哈希。
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$stmt = $conn->prepare($sql = "SELECT * FROM users WHERE email=?"); // otherwise $sql is not defined in catch()
if($stmt->execute([$_POST["li_email"]])){
// preventing sql injection
if(($data = $stmt->fetch()) != false){
// only expecting 1 row from db since an email should be unique.
if(password_verify($_POST["li_email"], $data['hash'])){
// valid login
if(password_needs_rehash($data['hash'], PASSWORD_DEFAULT, $options = ['cost' => 12])){
$newhash = password_hash($_POST["li_email"], PASSWORD_DEFAULT, options);
// store new hash in db.
}
} else {
header('Location: http://' . $_SERVER['HTTP_HOST'] . '?error=loginfailed');
exit();
}
} else {
// no results
}
} else {
// query failed
}
} catch(PDOException $e) {
echo $sql . "<br>" . $e->getMessage();
}
Just for the record, a sanely refactored version of the above code, with some vulnerabilities and inconsistencies removed.只是为了记录,上述代码的合理重构版本,删除了一些漏洞和不一致之处。
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $conn->prepare("SELECT * FROM users WHERE email=?");
$stmt->execute([$_POST["li_email"]]);
$data = $stmt->fetch();
if($data && password_verify($_POST["li_password"], $data['hash'])) {
if(password_needs_rehash($data['hash'], PASSWORD_DEFAULT, $options = ['cost' => 12])){
$newhash = password_hash($_POST["li_password"], PASSWORD_DEFAULT, options);
// store new hash in db.
}
} else {
header('Location: http://' . $_SERVER['HTTP_HOST'] . '?error=loginfailed');
exit();
}
Some key points:一些关键点:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.