Laravel 默认用 Hash::make() 自动生成 Argon2id 哈希(PHP≥7.3 且支持),需通过哈希串前缀 $argon2id$ 确认;参数调优需平衡资源与性能,存量密码须用 Hash::needsRehash() 检查升级;验证必须统一用 Hash::check(),数据库字段至少 VARCHAR(255)。

直接用 Hash::make() 就行,Laravel 会自动选 Argon2id(只要 PHP ≥ 7.3 且环境支持),不用手动调 password_hash()。
怎么确认当前用了 Argon2id
别看 config/hashing.php 里写的 driver,得看实际生成的哈希串开头:
-
$argon2id$v=19$m=65536,t=4,p=3$...—— 这才是 Argon2id -
$2y$12$...或$2b$12$...—— 还是 bcrypt - 如果
Hash::make('test')返回的是$2y$开头,说明要么 PHP 版本 config/hashing.php 里硬写了'driver' => 'bcrypt'
检查命令:php -i | grep -i argon;或在代码里跑 var_dump(defined('PASSWORD_ARGON2ID'));
调整 Argon2id 参数要小心内存和时间
Argon2id 的 memory、time、threads 不是越大越安全,而是得平衡服务器资源和用户体验:
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
-
memory默认 1024(KB),设到 65536(64MB)时单次哈希可能吃掉上百 MB 内存峰值,高并发登录页容易 OOM -
time默认 2,设成 4 后平均耗时从 ~150ms 跳到 ~400ms,在 QPS > 50 的登录接口上容易堆积请求 -
threads设太高反而因上下文切换变慢,一般保持 2 或 3 即可,别盲目设成 CPU 核数 - 改完参数后必须用
Hash::needsRehash($user->password)检查存量用户,否则老用户永远不升级
验证失败却没报错?可能是哈希格式不匹配
Hash::check() 对非 Argon2id 哈希串(比如旧 bcrypt 或手动生成的 password_hash(..., PASSWORD_ARGON2ID))会静默返回 false,不会抛异常:
- 如果你从旧系统迁移过密码字段,且里面混着
md5()或sha256()结果,Hash::check()一律返回false - 手动用
password_hash()生成的 Argon2id 哈希,虽然格式对,但 Laravel 的Hash::check()可能因 salt 解析逻辑差异而失败(尤其跨 PHP 版本) - 正确做法:所有密码哈希必须统一走
Hash::make(),所有验证必须走Hash::check(),二者绑定使用 - 数据库字段长度必须是
VARCHAR(255),Argon2id 哈希最长可达 250 字符,VARCHAR(60)会截断
为什么不能在模型 mutator 里调 Hash::make()
写 setPasswordAttribute() 并在里面调 Hash::make() 是危险反模式:
- Eloquent 在 fill()、update()、save() 等多个生命周期中可能反复触发该 mutator,导致密码被多次哈希(比如
$user->password = '123'→ 哈希一次;再$user->save()→ 又拿哈希值当明文再哈希一次) - 一旦发生,
Hash::check()永远验证失败,且无法还原 - 正确位置只应在控制器或 Form Request 的验证/存储逻辑里调一次
Hash::make() - 如果要用自动处理,应改用 Laravel 的
casts+ 自定义 cast 类,而非 mutator
Argon2id 的真正难点不在参数调优,而在整个哈希生命周期的控制——从生成、存储、验证到升级,任何一环脱钩都会让安全形同虚设。










