Lzh on GitHub

简介

Laravel 的 Hash 门面提供了安全的 Bcrypt 和 Argon2 哈希,用于存储用户密码。如果你使用的是 Laravel 的应用程序起始套件,注册和认证默认将使用 Bcrypt。

Bcrypt 是哈希密码的理想选择,因为它的 “工作因子” 是可调的,这意味着随着硬件性能的提升,生成哈希所需的时间也可以增加。在对密码进行哈希时,慢反而是有益的。算法生成哈希所需时间越长,恶意用户生成可能用于暴力破解攻击的 “彩虹表” 所需的时间也就越长。

配置

默认情况下,Laravel 在对数据进行哈希时使用 bcrypt 哈希驱动。不过,Laravel 还支持其他几种哈希驱动,包括 argon 和 argon2id。

你可以通过设置 HASH_DRIVER 环境变量来指定应用程序使用的哈希驱动。但如果你想自定义 Laravel 所有哈希驱动的选项,应该使用 Artisan 命令 config:publish 发布完整的哈希配置文件:

php artisan config:publish hashing

基本用法

密码哈希

你可以通过调用 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->user()->fill([
            'password' => Hash::make($request->newPassword)
        ])->save();

        return redirect('/profile');
    }
}

调整 Bcrypt 工作因子

如果你使用的是 Bcrypt 算法,make 方法允许通过 rounds 选项管理算法的工作因子;不过,Laravel 默认管理的工作因子对于大多数应用来说已经足够:

$hashed = Hash::make('password', [
    'rounds' => 12,
]);

调整 Argon2 工作因子

如果你使用的是 Argon2 算法,make 方法允许通过 memorytimethreads 选项来管理算法的工作因子;同样,Laravel 默认管理的值对于大多数应用来说已经足够:

$hashed = Hash::make('password', [
    'memory' => 1024,
    'time' => 2,
    'threads' => 2,
]);
有关这些选项的更多信息,请参考 PHP 官方文档中关于 Argon 哈希的说明。

验证密码是否与哈希匹配

Hash 门面提供的 check 方法可以用来验证给定的明文字符串是否与某个哈希值匹配:

if (Hash::check('plain-text', $hashedPassword)) {
    // 密码匹配...
}

判断密码是否需要重新哈希

Hash 门面提供的 needsRehash 方法可以用来判断自密码被哈希以来,哈希器的工作因子是否发生了变化。有些应用会在用户认证过程中执行此检查:

if (Hash::needsRehash($hashed)) {
    $hashed = Hash::make('plain-text');
}

哈希算法验证

为了防止哈希算法被篡改,Laravel 的 Hash::check 方法会首先验证给定的哈希值是否使用应用程序配置的哈希算法生成。如果算法不一致,将会抛出 RuntimeException 异常。

对于大多数应用来说,这是预期行为,因为哈希算法通常不会更改,不同算法可能意味着存在恶意攻击。然而,如果你需要在应用中同时支持多种哈希算法(例如在从一种算法迁移到另一种算法时),可以通过将 HASH_VERIFY 环境变量设置为 false 来禁用哈希算法验证:

HASH_VERIFY=false