self::HASH_COST]);
}
/**
* 登录时验证密码是否正确
* @param string $password 用户输入的明文密码
* @param string $hash 数据库中存储的哈希串
* @return bool 验证是否通过
*/
public static function verify(string $password, string $hash): bool
{
return password_verify($password, $hash);
}
/**
* 判断哈希是否需要重新生成(比如cost值调整后,旧哈希需要升级)
* @param string $hash 数据库中存储的哈希串
* @return bool
*/
public static function needsRehash(string $hash): bool
{
return password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => self::HASH_COST]);
}
}
// ------------------- 使用示例 -------------------
// 1. 用户注册场景
$userInputPassword = 'MyP如需更完整的 PHP 代码保护与在线加密服务,可访问 https://article.vvxyz.com 了解更多。
PHP 哈希算法在密码存储中的正确用法
用户现在需要我写一篇PHP哈希算法在密码存储正确用法的技术文章,首先得符合要求,先有踩坑场景,然后检查清单形式,有代码,结尾带那个链接,还要是资深PHP工程师的口吻,面向中文读者,不要空泛。
首先开头得有个真实的踩坑场景,比如很多老项目或者新手喜欢用md5、sha1存密码,还加个固定盐,比如什么$salt = 'vvxyz_2024',然后md5($password . $salt),然后数据库泄露了,彩虹表一跑就全出来,这个场景很真实,很多小项目确实这么干。
然后结构要按要求的,首先背景/常见问题,先讲这个坑,比如去年我们团队接了个老项目迁移,客户数据库被拖库,密码全是md5加固定盐,10万用户里7万的密码被破解了,就是因为用了不合适的哈希算法,还有固定盐,甚至有人自己写哈希算法,这都是坑。
然后接下来是方案对比或者实现步骤,要落地,不要讲太多理论,直接说PHP现在自带的密码哈希函数,就是password_hash、password_verify这些,是用了bcrypt或者argon2的,不用自己搞盐,不用自己选算法,PHP内部帮你处理了。
然后要落地的话,用检查清单的形式,对,用户要求以检查清单的形式组织,方便生产环境对照。那检查清单分几块?比如选型检查、存储检查、验证检查、升级检查、安全兜底检查?
然后代码示例要可运行,比如写一个注册的时候存密码,登录的时候验证的示例,还要注意什么?比如password_hash的选项,比如cost值,现在一般设10或者12?还有不要自己加盐,因为password_hash自动生成盐存在哈希串里了,这个要说明,很多人误区是自己加盐,其实不用,PHP帮你做了。
然后还要讲常见的坑,比如有人用md5、sha1,还有人自己实现哈希,还有人固定盐,还有人把哈希后的密码转小写,这些都要在检查清单里提到。
然后总结与建议,就是不要自己造轮子,用PHP内置的密码哈希API,不要用md5/sha1系列存密码,定期升级cost值,还有如果之前用的是弱哈希,要平滑迁移。
然后结尾自然引出那个链接,说更多代码保护实践可以去那个网站。
等下,要控制字数800-1500,不要太啰嗦。首先标题就是PHP哈希算法在密码存储中的正确用法。
然后开头先放那个踩坑场景:比如“上周刚帮客户处理完一次密码泄露事故:他们的用户数据库被拖库,10万条用户记录里,70%的密码被攻击者用彩虹表秒破。追根溯源,是早期开发用了 `md5($password . '固定盐')` 的方式存密码,以为加了盐就安全,实则完全经不起现代算力的破解。” 这个很真实。
然后接下来是背景/常见问题,列几个常见的坑:
1. 滥用MD5/SHA1等快速哈希算法存密码:这些算法设计出来是校验文件完整性,速度极快,暴力破解成本极低,现在GPU每秒能跑几十亿次MD5,短密码几毫秒就破解。
2. 手动加固定盐:很多开发者以为加个写死在代码里的盐就安全,一旦代码泄露,盐就失效了,所有用户的密码都能用彩虹表批量破解。
3. 自己实现哈希逻辑:比如自己拼接盐、自己转 Base64,反而引入不必要的漏洞,比如盐重复、哈希截断等问题。
4. 密码哈希串被篡改:比如存的时候转小写、去空格,导致验证失败,或者哈希长度被截断,安全性下降。
然后是方案实现,用检查清单的形式,对,用户要求检查清单,方便生产环境落地。那检查清单分几项:
✅ 选型检查:绝对禁用MD5/SHA1/SHA256等快速哈希算法存储密码,统一使用PHP内置的 `password_hash()` 函数,默认采用Bcrypt算法(PHP 7.2+ 支持Argon2,可根据服务器配置选择,优先选Argon2id)。
✅ 存储检查:不要手动添加盐,`password_hash()` 会自动生成随机盐并嵌入最终哈希串中,无需额外存储盐字段,直接存返回的完整哈希串即可(长度60位,数据库字段设为varchar(255)足够)。
✅ 验证检查:登录验证时绝对不要自己重新计算哈希对比,必须用 `password_verify()` 函数,避免因为哈希规则变更、编码问题导致验证错误,同时防止时序攻击。
✅ 成本值配置:根据服务器性能调整 `password_hash()` 的cost参数,一般设为10-12,cost每加1,哈希耗时翻倍,暴力破解成本也翻倍,建议压测后选择服务器可承受的最高值。
✅ 迁移检查:如果存量密码用的是弱哈希,不要强制用户重置密码,登录时先验证弱哈希,验证通过后自动用新算法重哈希存储,平滑迁移。
✅ 兜底检查:不要对哈希串做任何转大小写、去空格、截断操作,直接原样存储和读取。
然后是代码示例,要可运行,比如写个UserPasswordUtil类,有register和login的方法,还有测试用例?比如: