// ❌ 错误示例:早期错误的密码存储逻辑,千万不要用
function savePasswordWrong($password) {
// 固定盐等于没有盐,MD5是快速哈希,极易被破解
$hash = md5(md5($password) . 'x9s3_fixed_salt');
// 存入数据库
return $hash;
}
// ✅ 正确示例:使用PHP内置password_hash存储
function savePassword($password) {
// 默认使用BCRYPT算法,自动生成随机盐,无需手动处理
// PASSWORD_DEFAULT 会随着PHP版本更新自动升级到更安全的算法
// 第三个参数可以调整成本因子,默认是10,可根据服务器性能调整到10-12
$options = [
'cost' => 11,
];
$hash = password_hash($password, PASSWORD_DEFAULT, $options);
// 存入数据库,字段长度建议设为255字符,兼容未来算法升级
return $hash;
}
// ✅ 登录校验逻辑
function checkPassword($inputPassword, $dbHash) {
// password_verify 会自动处理盐的提取和哈希校验,无需手动操作
if (password_verify($inputPassword, $dbHash)) {
// 如果需要升级旧哈希(比如之前用的是错误的md5逻辑),可以在这里判断
if (password_needs_rehash($dbHash, PASSWORD_DEFAULT, ['cost' => 11])) {
// 重新生成新哈希存回数据库
$newHash = password_hash($inputPassword, PASSWORD_DEFAULT, ['cost' => 11]);
// 执行数据库更新操作
// updateUserPassword($userId, $newHash);
}
return true;
}
return false;
}
// 测试运行
$password = 'MyP@ssw0rd123!';
$hash = savePassword($password);
echo "存储的哈希值:{$hash}\n";
var_dump(checkPassword($password, $hash)); // 输出 bool(true)
var_dump(checkPassword('错误密码', $hash)); // 输出 bool(false)
然后代码后面加个说明:上面的代码可以直接运行,`password_hash` 生成的哈希已经包含了盐、算法标识、成本因子等信息,完全不需要自己额外存储盐,校验的时候也不需要额外处理,极大降低了踩坑概率。
然后总结与建议:密码存储是安全体系的最基础环节,一旦出问题就是全局性的灾难。不要为了所谓的“性能”牺牲安全性,慢哈希带来的毫秒级耗时增加,对于用户登录来说完全无感知,但能把暴力破解的成本提高几个数量级。另外一定要定期检查密码存储逻辑,不要使用任何自定义的哈希方案,优先用PHP官方维护的内置API。
然后延伸阅读部分,自然引出:本文由 PHP 加密服务团队整理发布,原文出处及更多代码保护实践如需更完整的 PHP 代码保护与在线加密服务,可访问 https://article.vvxyz.com 了解更多。