登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  php教程

PHP password_needs_rehash 如何判断算法参数已经过时

来源:17golang原创

时间:2026-09-14 22:01:50 139浏览 收藏

登录功能上线一段时间后,常见的一类“没有报错但安全策略没升级”问题是:数据库里的密码哈希仍然能验证成功,却已经不符合当前的算法或 cost 配置。处理这件事不能直接比较两次哈希,也不能只看到哈希字符串变长就改库。正确做法是先用 password_verify() 认证,再用 password_needs_rehash() 判断策略是否落后,只有两个判断都成立时,才用本次登录得到的明文密码生成新哈希并覆盖旧值。

官方地址:https://www.php.net/manual/en/function.password-needs-rehash.php

要点速览
  • true 表示哈希与当前算法或 options 不匹配,不表示用户密码错误。
  • 哈希升级必须发生在 password_verify() 成功之后,函数本身不能验证 MD5 或 SHA1。
  • PASSWORD_DEFAULT 可能随 PHP 版本变化,数据库字段应能容纳未来的完整哈希。

password_needs_rehash 比较的到底是什么

PHP 的密码哈希是自描述字符串,通常携带算法标识、算法参数和随机 salt。password_needs_rehash($hash, $algo, $options) 会拿这些信息与当前传入的算法和 options 比较;只要算法不同,或关键参数不符合,就返回 true。所以它回答的是“这条哈希要不要按当前策略重算”,不是“这次密码对不对”。

判断对象示例含义
算法PASSWORD_DEFAULT当前默认算法是否仍匹配
参数costmemory_cost计算强度是否符合策略
返回值true / false是否需要重新生成哈希
PHP password_needs_rehash 比较存储 hash、算法策略、cost 和随机 salt 的静态关系示意图
图1:PHP 密码哈希字段与当前策略的静态关系示意图,不代表本机运行结果。

例如当前策略从 bcrypt cost 12 提高到 13,旧哈希仍可能通过 password_verify(),但拿同一组新 options 判断时会得到 true。这正是渐进升级的入口:不用强迫所有用户一次性重置密码,而是在下一次成功登录时更新。

为什么必须先验证密码再重算哈希

故障复盘时最危险的改法,是拿请求参数直接调用 password_needs_rehash(),或者只要它返回 true 就把新哈希写回。该函数不检查明文密码,未验证的输入不应拥有改写用户凭据的机会。

 12];

// $password 是本次登录输入,$storedHash 来自用户记录。
if (password_verify($password, $storedHash)) {
    // 只有认证成功,才判断旧哈希是否落后于当前策略。
    if (password_needs_rehash($storedHash, $algo, $options)) {
        // 重新使用已验证的明文密码生成随机盐哈希。
        $newHash = password_hash($password, $algo, $options);
        // 用条件更新或事务写回,避免覆盖并发修改后的记录。
        updateUserPasswordHash($userId, $newHash);
    }
    loginUser($userId);
}
?>

这里有两个独立的成功条件:第一个确认“人知道密码”,第二个确认“哈希策略需要升级”。如果第一个失败,流程直接结束;如果第一个成功、第二个为 false,照常登录但不写库;两个条件都满足,才进入重算和写回。

PHP password_verify、password_needs_rehash、password_hash 与 users.password_hash 的认证升级边界示意图
图2:登录认证与哈希升级职责边界示意图,重点看验证结果与新哈希写回之间的约束。

旧哈希升级时最容易漏掉的三个边界

第一,不要把 MD5、SHA1 或自定义字符串直接交给这个函数期待它“识别并修复”。这套 API 面向 password_hash() 生成的哈希;真正的遗留算法需要在兼容认证分支中单独验证,确认密码正确后再转成新格式。

第二,升级参数必须来自统一策略,而不是散落在登录控制器里的魔法数字。bcrypt 的 cost、Argon2 的 memory_costtime_costthreads 都应和实际机器负载一起评估。提高 cost 会增加登录计算时间,不应只因为数字更大就盲目修改。

第三,保存哈希时不要截断字段,也不要手工固定 salt。PHP 手册说明 PASSWORD_DEFAULT 的默认算法未来可能变化,常见的密码字段应按可变长度设计,例如使用能容纳完整哈希的 255 字节字段;更新动作还应处理并发登录,避免后写入的旧策略覆盖先写入的新策略。

常见问题

password_needs_rehash 返回 true 是密码错了吗?

不是。它只说明算法或 options 与当前策略不一致,密码是否正确必须由 password_verify() 判断。

每次登录都要重新生成密码哈希吗?

不需要。只有验证成功且 password_needs_rehash() 返回 true 时才重算,其他情况直接完成登录。

可以用 password_needs_rehash 判断 MD5 哈希吗?

不能把它当作 MD5/SHA1 识别器。遗留哈希要保留独立的兼容校验,成功后再用现代密码 API 完成迁移。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>