翻出十年前的老系统,用户表里密码列全是32位MD5。MD5快,快到GPU每秒能算几十亿次,意味着拖库之后密码等于明文。这课补起来不贵,PHP自带的password_hash就是标准答案。
它默认用bcrypt,自动生成盐、自动处理算法版本,验证时password_verify连计时攻击都防了。用法五行。
<?php
// 注册:存哈希
$hash = password_hash($password, PASSWORD_DEFAULT);
// INSERT INTO users (name, pwd) VALUES (?, $hash)
// 登录:验证
if (password_verify($password, $row['pwd'])) {
// 哈希算法过时了就顺手升级,用户无感
if (password_needs_rehash($row['pwd'], PASSWORD_DEFAULT)) {
$newHash = password_hash($password, PASSWORD_DEFAULT);
// UPDATE users SET pwd = $newHash
}
// 登录成功逻辑
老用户迁移不用强迫全员改密码。方案是平滑过渡:登录验证时先试password_verify,对不上再回退比一次旧MD5,比中了就把MD5原文当场换成bcrypt哈希。用户登录一次升级一个,半年后剩余的没登录过的MD5账号可以强制走找回流程。
// 老系统兼容登录
$md5 = md5($password); // 仅过渡期使用
if (password_verify($password, $row['pwd'])) {
$ok = true; // 已是新版哈希
} elseif ($md5 === $row['pwd']) {
$ok = true; // 命中旧MD5,当场升级
$stmt->execute([password_hash($password, PASSWORD_DEFAULT), $row['id']]);
}
cost参数默认10,服务器性能好可以调到12,哈希耗时从几十毫秒变几百毫秒对登录体验无感,对爆破者就是灾难。密码存储这条线没有灰色地带:MD5、SHA1、无盐哈希,都该在今天之内进历史垃圾桶。
A5创业网 版权所有