password_hash()是唯一推荐的密码加密方式,因其自动处理salt、算法和参数并支持未来升级;md5/sha1不安全,手动拼接salt易出错;thinkphp中应直接调用原生函数而非封装层;注册时用password_default生成哈希存入varchar(255)字段,登录时用password_verify()验证,迁移时用password_needs_rehash()升级旧哈希。

password_hash() 是唯一推荐的密码加密方式,别碰 md5()、sha1() 或手动拼接 salt。
为什么不能用 md5($password . $salt)
-
md5()算法已被 GPU 集群秒破,彩虹表覆盖全网常见密码 - 手动拼接的 salt 如果用
uniqid()或固定字符串,长度不足、熵值低、没做 base64 编码,数据库里存的其实是“伪盐” - 盐值和哈希混在一起存,后续无法升级算法(比如从 bcrypt 切到 argon2)
- ThinkPHP 自己封装的
think\facade\Hash::make()底层其实也是调password_hash(),但没必要多一层抽象——直接用原生函数更可控
怎么在 ThinkPHP 注册时存密码
- 注册接口里直接调用
password_hash(),一行搞定:$hashed = password_hash($request->post('password'), PASSWORD_DEFAULT); - 存进数据库字段(建议
varchar(255),bcrypt 哈希最长约 60 字符,argon2 更长) - 不要自己生成 salt,不要存 salt 字段,
PASSWORD_DEFAULT会把 salt、算法、成本参数全打包进哈希字符串里(如$2y$10$...)
登录验证必须用 password_verify()
- 查询用户后,拿到数据库里存的完整哈希字符串(不是截断过的,不是 substr 后的)
- 直接传给
password_verify():if (password_verify($inputPassword, $user['password'])) { /* 登录成功 */ } - 它会自动解析哈希里的算法标识、提取 salt、按对应参数重算一次,完全屏蔽细节
- 即使未来 PHP 升级默认算法(比如切到 argon2),老用户哈希仍能验证通过
容易被忽略的三个点
-
password_needs_rehash()必须用:老系统迁移到 TP6 时,如果原来用的是md5(),可在用户登录成功后加一层判断,自动升级哈希 - 数据库密码字段不能设成
char(32):那是为 md5 预留的,现在至少要varchar(255) - 日志和调试输出里绝不能打出来哈希值:哪怕只是
dump($user['password']),也属于敏感信息泄露
加密不是加个函数就完事,是整条链路的约束:存的时候不裸奔,查的时候不暴露,升级时不卡顿。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











