PHP 哈希算法在密码存储中的应用
在 Web 应用开发中,安全地存储用户密码是开发者不可推卸的责任。明文存储密码是严重安全隐患,而简单哈希(如 md5() 或 sha1())也早已被证明不安全。PHP 提供了现代、内置的密码哈希 API,专为密码场景设计。
为什么不能用普通哈希函数?
md5('password') 或 sha256('password') 缺乏盐值(salt)和可调慢速机制,易受彩虹表攻击与暴力破解。现代密码哈希必须满足:加盐(salted)、自适应慢速(adaptive slowness)、抗 GPU/ASIC 加速。
推荐方案:PHP 的 password_hash() 和 password_verify()
PHP 5.5+ 内置的 password_*() 函数默认使用 bcrypt 算法(PASSWORD_BCRYPT),自动处理盐值生成、格式编码与验证逻辑,且向后兼容。
✅ 正确示例:注册与登录
// 注册:哈希密码并存入数据库
$password = $_POST['password'];
$hashedPassword = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
// 存入数据库字段(如 users.password)
// $pdo->prepare("INSERT INTO users (username, password) VALUES (?, ?)")->execute([$user, $hashedPassword]);
// 登录:验证密码
$storedHash = $dbUser['password']; // 从数据库读取的哈希字符串
if (password_verify($_POST['password'], $storedHash)) {
echo "登录成功!";
} else {
echo "密码错误。";
}
💡 password_hash() 返回的字符串已包含算法标识、成本因子(cost)、盐值与哈希结果(如 $2y$12$...),无需单独存储盐值 —— password_verify() 可完整解析并校验。
⚠️ 重要提醒:切勿自行实现盐值、拼接或多次哈希!避免使用
md5()、sha1()、crypt()(无参数)等过时方法。若需更高安全性,PHP 7.2+ 还支持 PASSWORD_ARGON2I 或 PASSWORD_ARGON2ID(需启用 sodium 扩展)。
🔍 额外建议
- 定期升级哈希:当用户下次登录时,可用
password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost'=>14])判断是否需用更强参数重哈希; - 密码强度策略:哈希只是防线一环,前端与后端仍需配合长度、复杂度校验;
- HTTPS 强制启用:防止密码在传输中被截获。
安全不是功能,而是贯穿始终的设计原则。用对 PHP 的密码哈希 API,就是为用户隐私筑起第一道坚实屏障。
```