Hash::make()仅用于密码哈希,不可逆;需加解密时用Crypt::encryptString()/decryptString(),确保APP_KEY一致且安全配置。

别用 hash() 存密码,也别自己拼盐或调 password_hash() —— Laravel 的 Hash::make() 和 Hash::check() 已经封装好所有安全细节,直接用就对了。
Hash::make() 为什么不能用来“加密字符串”
Hash::make() 是单向哈希,不是加密。它底层调用 password_hash(),目标是让密码不可逆、抗彩虹表、防暴力破解。一旦你传入 'hello',得到的是一串类似 $2y$10$... 的 60 字符哈希值,没有任何 Laravel 方法能把它变回 'hello'。
- 常见错误:把 API key 或邮箱用
Hash::make()存库,结果业务需要读原文时彻底卡死 - 正确做法:需可逆时改用
Crypt::encryptString(),且确保APP_KEY未泄露、未轮换 - 性能影响:
Hash::make()默认耗时约 100ms(cost=12),频繁用于非密码场景会拖慢接口
Hash::check() 必须配合数据库里存的完整哈希串
验证密码时,必须把用户输入的明文和数据库字段里存的**完整哈希字符串**(如 y$XzKqJZv7Q9nRtS8pWmLcOeFgHiJkLmNoPqRsTuVwXyZaBcDeFgHiJ)一起传给 Hash::check()。它内部会自动解析算法、cost、salt,再重新哈希比对。
- 错误写法:
$request->password === $user->password,永远为 false - 错误写法:
Hash::check($pwd, substr($hash, 0, 30)),截断后 salt 和参数丢失,校验必失败 - 数据库字段类型建议设为
varchar(255),bcrypt 固定 60 字符,argon2id 可能更长
怎么安全升级老密码哈希(比如从 bcrypt v10 到 v12)
全量重哈希不现实,服务器扛不住;放任不管又降低安全性。Laravel 提供了渐进式方案:Hash::needsRehash() + 登录时触发重哈希。
- 在登录成功后检查:
Hash::needsRehash($user->password, ['rounds' => 12]) - 只在
Auth::attempt()成功后才执行重哈希,避免被攻击者利用探测有效账号 - 注意:
needsRehash()不会自动升级算法(如从 bcrypt 切到 argon2id),只检测 cost 或选项变更 - 如果数据库里混着 md5 或 sha1 密码,
Hash::check()会直接返回false,得自己加迁移逻辑
最常被忽略的一点:哈希强度不是越高越好。cost=14 后单次哈希可能超 400ms,在高并发登录接口中容易堆积延迟——得结合服务器 CPU 和实际 QPS 测试后再调。


















