php动态网站开发如何加密用户密码_PHP动态网站密码加密技巧【方案】

8次阅读

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

php动态网站开发如何加密用户密码_PHP动态网站密码加密技巧【方案】

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免费学习笔记(深入)”;

典型翻车现场: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() 确认登录成功,再决定是否重哈希。

text=ZqhQzanResources