PHP密码加密必须用password_hash(),它自动加盐、默认bcrypt、支持自适应成本因子;禁用md5/sha1等不安全函数,存储须用VARCHAR(255),验证必须用password_verify(),迁移旧密码需配合password_needs_rehash()。

PHP 密码加密必须用 password_hash(),别碰 md5() 或 sha1()
明文存密码是严重安全漏洞,而手写哈希(比如 md5($pass))等于没加密。PHP 从 5.5 起内置的 password_hash() 和 password_verify() 是唯一推荐方案——它自动加盐、选算法(默认 bcrypt)、适配未来升级。
常见错误:用 md5() + 固定字符串拼接(如 md5($pass.'salt123')),这无法抵御彩虹表+暴力组合攻击;或误以为“加了 salt 就安全”,却忽略算法迭代次数和抗 GPU 计算能力。
-
password_hash()默认使用CRYPT_BLOWFISH(即 bcrypt),支持自适应成本因子(cost=10~12,越高越慢但越难爆破) - 生成的哈希字符串自带算法、cost、salt 信息,长度约 60 字符,**必须用
VARCHAR(255)存储**(别用CHAR(60)截断) - 永远不要自己实现 salt 逻辑或硬编码算法参数
注册时怎么调用 password_hash() 才不出错
最简可用写法就是一行:$hash = password_hash($password, PASSWORD_DEFAULT);。但要注意三个实际约束:
- 输入
$password必须是字符串,空值或null会返回false,需提前校验(如if (empty($password)) die('密码不能为空');) -
PASSWORD_DEFAULT当前是 bcrypt,但未来可能变(如 PHP 9 改用argon2id);若需长期兼容旧数据,可显式写PASSWORD_BCRYPT并固定['cost' => 12] - 数据库插入前务必用
mysqli_real_escape_string()或预处理语句,避免哈希中特殊字符(如$、/)引发 SQL 解析异常
登录验证必须用 password_verify(),不能 strcmp() 或 == 比较
从数据库取出的哈希字符串(如 $2y$12$abc...)和用户提交的明文密码,必须用 password_verify($input_pass, $stored_hash) 判断。直接用 == 或 strcmp() 对比哈希结果是错的——因为每次 password_hash() 生成的 salt 不同,相同密码哈希值也不同。
立即学习“PHP免费学习笔记(深入)”;
主要功能:1、新闻信息:可分多类(内部新闻,外部新闻等)2、产品展示:可分多类(分类一,分类二等)3、网站公告:网站公告添加多数据显示。4、动态添加公司介绍,联系方式等并可以扩展。5、网站留言:前台发布留言后台验证后显示6、新闻信息和产品展示动态添加meta标签:keywords,description ,同时url重写htm页面更好的被搜索引擎收入。后台用户名密码admin
典型翻车现场:if (md5($_POST['pass']) === $db_hash) { /* 登录成功 */ } —— 这种写法既不安全也不正确。
-
password_verify()内部自动解析哈希头里的算法、cost、salt,并用同样逻辑重算比对 - 它恒定时间比较(timing-safe),防止时序攻击;而
==在遇到首字符不同时立刻返回,可能被利用测出密码长度或部分字符 - 函数返回
true/false,不要用===强等判断,避免把false当字符串处理
迁移旧密码库时,password_needs_rehash() 是关键开关
如果老站用的是 md5() 或低 cost 的 bcrypt,上线新哈希逻辑后,不能强制所有用户改密码。正确做法是在用户下次登录时,用 password_needs_rehash() 检查旧哈希是否需升级:
// 登录成功后
if (password_needs_rehash($db_hash, PASSWORD_DEFAULT, ['cost' => 12])) {
$new_hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
// 更新数据库中的 password 字段
update_user_password($user_id, $new_hash);
}
这个函数会解析存储的哈希,对比当前 PASSWORD_DEFAULT 的默认 cost 和算法,只在不匹配时返回 true。漏掉这步,就等于长期保留弱哈希入口。
注意:password_needs_rehash() 不会验证密码是否正确,它只看哈希元数据——所以必须先用 password_verify() 确认登录成功,再决定是否重哈希。










