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

时间:2017-01-31 23:03:41

标签: php login php-password-hash

我有一个用于登录应用程序的处理文件。我要么不理解password_needs_rehash()的目的,要么就是不行。登录正在验证并将我传递到正确的页面。但我无法让代码甚至回应新的哈希。

我这样做是否正确?

if是否因为不需要重新散列而不抛出新散列?如果是这样,如果密码被正确地散列并存储在数据库中,何时需要重新设置密码?

我的处理文件如下:     

$email = $_POST["li_email"];

try {
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    // set the PDO error mode to exception
    $stmt = $conn->query("SELECT * FROM users WHERE email='$email'");
    $stmt->execute();
    while($row=$stmt->fetch()){ //for each result, do the following
        $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();
        }
    }
} catch(PDOException $e) {
    echo $sql . "<br>" . $e->getMessage();
}

$conn = null;

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

如果您更改通常引用$options的{​​{1}},则只需使用password_needs_rehash()函数。

成本越高,散列密码所需的CPU时间就越多,但破解密码的难度就越大。如果您更改主机或转移到基于云的系统,其中多台计算机可以为您计算哈希值,您可以自行决定增加它。

您只需要检查密码是否需要在用户登录时进行重新连接,因为password_verify()如果您更改了cost,仍然可以验证密码。如果此时password_needs_rehash()返回true,请将password_hash()与新选项一起使用并替换旧哈希。

$options

答案 1 :(得分:0)

仅仅是为了记录,上面代码的一个明确重构的版本,删除了一些漏洞和不一致。

$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_email"], $data['hash'])) {
    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();
}

一些关键点:

  • 无需暗示黑客拥有用户名和密码的明显错误消息。
  • 应严格避免数据库结构泄漏
  • 看到带有错误消息的SQL没有任何意义,因为它已经在代码
  • 如果执行失败,则表示系统错误,应予以相应处理