跳转到主要内容

什么是哈希

哈希(Hashing)指的是通过一种单向变换将明文数据(如密码)转换为定长字符串的处理方式。 相同输入总能生成相同的哈希,但无法通过哈希还原出原始明文。 Laravel 的 Hash 门面支持 bcryptArgon2 两种哈希算法,用于安全地保存密码。

算法对比

算法特点推荐用途
bcrypt可通过工作因子(rounds)调整计算成本,默认算法常规 Web 应用
argon2i可调整内存、时间、线程数,能抵御旁路攻击对安全性要求较高的场景
argon2idargon2i 与 argon2d 的混合,PHC 官方推荐新项目使用 Argon2 时
bcrypt 的「工作因子」用于控制生成哈希所需的时间。哈希越慢,抵御暴力破解的能力就越强。随着硬件性能提升,只要相应地增加工作因子即可保持安全等级。

哈希与校验流程


配置

Laravel 默认使用 bcrypt 驱动。可以通过 HASH_DRIVER 环境变量修改。
# .env
HASH_DRIVER=bcrypt  # bcrypt / argon / argon2id
要自定义哈希配置,可以通过 config:publish 发布配置文件。
php artisan config:publish hashing
发布后可在 config/hashing.php 中修改默认的工作因子等。

基本用法

对密码进行哈希

将密码明文传入 Hash::make() 就会返回哈希值。请将该哈希值保存到数据库。
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;

class PasswordController extends Controller
{
    public function update(Request $request): RedirectResponse
    {
        $request->validate([
            'password' => ['required', 'min:8', 'confirmed'],
        ]);

        $request->user()->fill([
            'password' => Hash::make($request->password),
        ])->save();

        return redirect('/profile');
    }
}
只将哈希值保存到数据库,绝不要保存明文密码。

调整 bcrypt 的工作因子

通过 rounds 选项可调整生成哈希的计算成本。值越大越安全,但耗时也会增加。 默认值(12)在多数应用场景下都足够。
$hashed = Hash::make('plain-text-password', [
    'rounds' => 14,
]);

调整 Argon2 的参数

使用 Argon2 时,可通过 memorytimethreads 选项调整计算成本。
$hashed = Hash::make('plain-text-password', [
    'memory'  => 65536, // KiB
    'time'    => 4,
    'threads' => 2,
]);
选项说明默认值
memory使用的内存量(KiB)65536
time迭代次数4
threads使用的线程数1
Argon2 参数的详细信息请参阅 PHP 官方文档

校验密码

使用 Hash::check() 可以判断明文密码是否与已保存的哈希匹配。 这是登录处理中最典型的用法。
use Illuminate\Support\Facades\Hash;

if (Hash::check($request->password, $user->password)) {
    // 密码匹配
} else {
    // 密码不匹配
}
如果使用 Auth::attempt(),Laravel 会自动进行这一处理,不需要你直接调用。 Hash::check() 适合手动校验当前密码的场合。
// 在修改密码表单中确认当前密码的例子
if (! Hash::check($request->current_password, $request->user()->password)) {
    return back()->withErrors(['current_password' => '当前密码不正确。']);
}

是否需要重新哈希

Hash::needsRehash() 可以判断哈希生成时的工作因子是否与当前配置不同。 在调整了工作因子后,可以用它来更新既有哈希。
use Illuminate\Support\Facades\Hash;

if (Hash::needsRehash($user->password)) {
    $user->update([
        'password' => Hash::make($plainTextPassword),
    ]);
}
下面是登录成功时进行重新哈希的例子。
// 在登录处理中执行重新哈希
if (Auth::attempt($credentials)) {
    if (Hash::needsRehash(Auth::user()->password)) {
        Auth::user()->update([
            'password' => Hash::make($credentials['password']),
        ]);
    }

    return redirect()->intended('/dashboard');
}
随着硬件性能提升,请定期审查工作因子以保持安全性。利用 needsRehash(),可以在用户登录的自然时机顺便更新密码哈希。

哈希算法校验

默认情况下,Hash::check() 会验证哈希是否由当前配置的算法生成。 如果算法不同则会抛出 RuntimeException 这可以防止篡改哈希算法所带来的攻击。 在需要同时支持多种算法(例如算法迁移期间)时,可以将 HASH_VERIFY 设置为 false 来禁用该校验。
# .env
HASH_VERIFY=false
设置 HASH_VERIFY=false 将禁用算法校验。请只在迁移期间使用,迁移完成后请恢复为 true(默认值)。

小结

想做的事方法
对密码进行哈希Hash::make($password)
校验哈希Hash::check($plain, $hash)
判断是否需要重新哈希Hash::needsRehash($hash)
修改哈希驱动使用 HASH_DRIVER 环境变量
关闭算法校验设置 HASH_VERIFY=false

下一步

认证入门

学习使用 Hash::check() 实现登录处理等,了解认证的整体流程。
最后修改于 2026年7月13日