【问题标题】:Is it necessary to password_hash again when first password_hash already valid ? I'm newbie当第一个密码哈希已经有效时,是否需要再次密码哈希?我是新手
【发布时间】:2026-01-07 05:15:01
【问题描述】:

我阅读并遵循了关于 password_hash 的 PHP 文档并得到了这个:

    <?php
// first determine if a supplied password is valid
$options = ['cost' => 12,];

$hashedPassword = password_hash($plaintextPassword, PASSWORD_DEFAULT, $options);
if (password_verify($plaintextPassword, $hashedPassword)) {

    // now determine if the existing hash was created with an algorithm that is
    // no longer the default
    if (password_needs_rehash($hashedPassword, PASSWORD_DEFAULT)) {

        // create a new hash with the new default
        $newHashedPassword = password_hash($plaintextPassword, PASSWORD_DEFAULT);

        // and then save it to your data store
        //$db->update(...);
    }
}
?>

我真的很想知道当第一个哈希已经有效时是否有必要再次 hash_password。

【问题讨论】:

  • hash_password 是什么?

标签: php hash passwords bcrypt php-password-hash


【解决方案1】:

第二个检查是查看密码是否使用当前的 PASSWORD_DEFAULT 加密。

与其说是密码检查,不如说是 PHP 兼容性/持续的安全性。

看看: http://php.net/manual/en/function.password-hash.php

md5($password) 的旧时光一去不复返了……

【讨论】:

  • thz 还有一个问题是我应该把 $option = cost 12 放到 New password_hash $newHashedPassword 中吗?
【解决方案2】:

从技术上讲,password_hash 的第二次调用是不必要的。然而,它非常有用,不应该被忽略!正如 Mark 已经提到的,第二次调用有助于使您存储的哈希值保持最新。

但是您的代码-sn-p 中有一个非常重要的缺陷。您从文档中复制的部分很好,但您扩展它的方式不正确。 那么发生了什么?第一次调用password_hash明文密码 创建一个散列。然后使用参数$plaintextPassword$hashedPassword 调用password_verify。这是有问题的部分。此调用将始终产生TRUE,因为您正在验证明文密码是否与刚刚创建的自身哈希匹配。这永远不会失败,这最终会使条件变得无用。

错误是您第一次调用password_hash。此时您不会散列$plaintextPassword。相反,您应该从数据库中检索该用户已存储的密码哈希。接下来,您将以如下方式调用password_verifypassword_verify($plaintextPassword, $hashedPasswordFromDatabase))。这可以确保输入的明文密码与您已经知道的密码哈希匹配。

// drop that line
//$hashedPassword = password_hash($plaintextPassword, PASSWORD_DEFAULT, $options); 

// and replace it with something like this
$hashedPasswordFromDatabase = $db->getPasswordHashForUserId(42);

// match the plaintext pw an the pw from db 
if (password_verify($plaintextPassword, $hashedPasswordFromDatabase)) 
{
    ...

然后password_needs_rehash 检查密码哈希(取自数据库)是否仍然是最新的。如果它发现哈希已被弃用,则条件成立并再次调用password_hash。要了解这为何有用,请想象以下情况:您在接下来的几天发布您的网站。用户创建帐户,currently active hashing-algorithm CRYPT_BLOWFISH 用于创建用户的哈希值。您的网站变得如此成功,它在 2020 年仍然活跃。到那时(很可能更早)更好的散列算法成为默认值。然后将使用更好的算法自动创建新用户的密码,因为您使用的是常量PASSWORD_DEFAULT,它将在另一个 PHP 版本中返回其他散列算法。对于新用户来说,这很好。但是,如果您的代码中没有第二次调用 password_hash,则已经存在的用户密码不会重新散列,实际上也不会更新。 p>

长话短说:在您的 sn-p 中进行第二次调用,以使您的代码更具前瞻性。


解决您的其他问题:

12 的成本现在可能没问题,但您应该不时调整这个值。拍摄from the docs

建议您在服务器上测试此功能,并调整成本参数,使该功能在交互式系统上的执行时间少于 100 毫秒。

因此,您应该增加它,使其在您的服务器硬件上产生所需的延迟。但也请注意,将could make you vulnerable 增加太多会导致拒绝服务攻击。

有关密码哈希的非常详细的介绍,请查看crackstation 上的这篇精彩文章:https://crackstation.net/hashing-security.htm

【讨论】: