电话
400 9058 355
PHP密码加密必须用password_hash(),它自动加盐、默认bcrypt、支持自适应成本因子;禁用md5/sha1等不安全函数,存储须用VARCHAR(255),验证必须用password_verify(),迁移旧密码需配合password_needs_rehash()。
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,越高越慢但越难爆破)VARCHAR(255) 存储**(别用 CHAR(60) 截断)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 不同,相同密码哈希值也不同。
典型翻车现场:if (md5($_POST['pass']) === $db_hash) { /* 登录成功 */ } —— 这种写法既不安全也不正确。
password_verify() 内部自动解析哈希头里的算法、cost、salt,并用同样逻辑重算比对== 在遇到首字符不同时立刻返回,可能被利用测出密码长度或部分字符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() 确认登录成功,再决定是否重哈希。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...