简体   繁体   English

我什么时候需要使用 password_needs_rehash()?

[英]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 .您只需要在用户登录时检查密码是否需要重新哈希,因为如果您更改了$optionspassword_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:一些关键点:

  • no need to hint a hacker with distinct error messages for username and password.无需用用户名和密码的不同错误消息提示黑客。
  • a database structure leak should be strictly avoided应严格避免数据库结构泄漏
  • there is no point in seeing SQL with error message as it is already in the code看到带有错误消息的 SQL 是没有意义的,因为它已经在代码中了
  • if execute failed, that's a system error and should be treated accordingly如果执行失败,这是一个系统错误,应该相应地处理

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

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