PHP官方推荐使用password_hash()生成含盐哈希并存入数据库,登录时用password_verify()校验,自动处理算法、cost和salt,无需手动拼接或字符串比较,且支持平滑升级与时序攻击防护。

直接用 password_hash() 生成哈希,存进数据库;登录时用 password_verify() 校验——这是 PHP 官方推荐、开箱即用的安全方案,不用自己管盐、不拼接、不比对字符串。
注册时生成并存储密码哈希
用户提交密码后,立刻调用 password_hash() 处理,把返回的完整哈希字符串存入数据库即可:
- 用
PASSWORD_DEFAULT(推荐)或显式指定PASSWORD_BCRYPT,避免硬编码 MD5/SHA1; - 哈希值长度固定为 60 字符(
$2y$开头),但未来算法可能变长,数据库字段建议设为VARCHAR(255); - 不要对原始密码先做 MD5 或其他处理再传入
password_hash(),会削弱密码强度; - 无需手动提供 salt,函数自动随机生成并嵌入结果中;
- 密码超长(>72 字节)会被截断,注意前端限制或提示用户长度范围。
登录时验证密码是否正确
用户输入密码后,从数据库查出对应用户的哈希值,交给 password_verify() 判断:
- 传入明文密码和数据库里存的完整哈希字符串,函数自动解析算法、cost 和 salt 并完成比对;
- 返回
true表示密码正确,false表示错误或哈希格式异常,不要据此向用户透露具体失败原因; - 切勿用
==或===直接比较两个哈希值,也不要把用户输入再password_hash()一次去比对; - 该函数采用恒定时间比较,能有效防御时序攻击。
平滑升级旧哈希以适配更强参数
当 PHP 升级或需提高 bcrypt 成本因子(如从 cost=10 改为 cost=12)时,可通过 password_needs_rehash() 实现无感升级:
立即学习“PHP免费学习笔记(深入)”;
- 用户下次成功登录时,先检查当前哈希是否满足新参数要求;
- 若
password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 12])返回true,就用新参数重新哈希密码,并更新数据库; - 历史哈希仍可正常验证,不影响老用户登录;
- 升级动作只在验证通过后触发,不增加额外负担。
额外建议:别踩这些常见坑
很多项目还在用过时方式,容易被撞库或爆破:
- 禁止明文存密码,也别用固定 salt + MD5/SHA1 这类快哈希;
- 日志里绝不记录用户明文密码,哪怕调试也不行;
- 注册和登录流程中,原始密码仅在内存中短暂存在,不落地、不缓存;
- 如果要用 Argon2 等更现代算法,确认 PHP 编译时已启用 libargon2 支持。



















