多因素认证
介绍
Filament 用户默认可以使用邮箱和密码登录。不过,你可以启用多因素认证(MFA),为用户提供额外的安全保障。
启用MFA后,用户在通过身份验证并访问应用之前必须执行额外的验证。

Filament 包括两种可以开箱即用的 MFA 方法:
- 应用身份认证使用与 Google 身份验证器兼容的应用(如 Google 身份验证器、Authy 或 Microsoft 身份验证器应用)生成用于验证用户的基于时间的一次性密码(TOTP)。
- 电子邮件身份认证向用户的电子邮件地址发送一个一次性代码,用户必须输入该代码以验证其身份。
在 Filament 中,用户在他们的个人资料(profile)页面设置多因素身份验证。如果你使用 Filament 的个人资料页面功能,设置多因素身份验证将自动将对应的 UI 元素添加到个人资料页面:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->profile();
}

应用身份认证
要在面板中启用应用身份验证,你必须首先向 users 表(或此面板中“可身份验证(authenticatable)” 的 Eloquent 模型的任何表)添加一个新字段。该字段需要存储用于生成和验证基于时间的一次性密码的密钥。它可以是迁移中的普通 text() 字段:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::table('users', function (Blueprint $table) {
$table->text('app_authentication_secret')->nullable();
});
在 User 模型中,你需要实现 HasAppAuthentication 接口并使用 InteractsWithAppAuthentication trait。它提供了与密钥及其他集成信息交互的必要方法:
use Filament\Auth\MultiFactor\App\Contracts\HasAppAuthentication;
use Filament\Auth\MultiFactor\App\Concerns\InteractsWithAppAuthentication;
use Filament\Models\Contracts\FilamentUser;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements FilamentUser, HasAppAuthentication, MustVerifyEmail
{
use InteractsWithAppAuthentication;
// ...
}
TIP
为了兼顾速度与简洁,Filament 提供了默认实现;不过,你也可以自行实现所需的方法,从而自定义列名,或者将密钥存储在完全独立的表中。
最后,你应该在面板中激活应用身份认证功能。为此,请在配置中使用 multiFactorAuthentication() 方法,并传入一个 AppAuthentication 实例:
use Filament\Auth\MultiFactor\App\AppAuthentication;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->multiFactorAuthentication([
AppAuthentication::make(),
]);
}
NOTE
为防止同一个应用验证码被多次接受,请使用支持原子锁的默认缓存存储(例如数据库或 Redis 缓存驱动)。所有应用服务器必须使用相同的缓存后端。若采用其他缓存配置,并发请求可能会导致同一个验证码被多次接受。
设置应用恢复码
如果用户丢失访问他们的双因素身份验证应用的权限,他们将无法登录到应用中。为了防止这种情况,你可以生成一组恢复码,用户可以在失去对双因素身份验证应用的访问权限时使用这些代码登录。
与 app_authentication_secret 字段类似, 你应该向 users表(或面板中使用 “authenticatable” Eloquent 模型的任何表)添加一个新字段。该字段用于存储恢复码。它可以是迁移中的普通 text() 字段:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Schema::table('users', function (Blueprint $table) {
$table->text('app_authentication_recovery_codes')->nullable();
});
接下来,你需要在 User 模型中实现 HasAppAuthenticationRecovery 接口,并使用 InteractsWithAppAuthenticationRecovery trait。该 trait 提供了与恢复码进行交互的必要方法:
use Filament\Auth\MultiFactor\App\Contracts\HasAppAuthentication;
use Filament\Auth\MultiFactor\App\Concerns\InteractsWithAppAuthentication;
use Filament\Auth\MultiFactor\App\Contracts\HasAppAuthenticationRecovery;
use Filament\Auth\MultiFactor\App\Concerns\InteractsWithAppAuthenticationRecovery;
use Filament\Models\Contracts\FilamentUser;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements FilamentUser, HasAppAuthentication, HasAppAuthenticationRecovery, MustVerifyEmail
{
use InteractsWithAppAuthentication;
use InteractsWithAppAuthenticationRecovery;
// ...
}
TIP
由于 Filament 在 User 模型上使用了接口,而不是假定存在 app_authentication_recovery_codes 字段,因此你可以使用任何你想要的字段名。如果你的恢复码保存在不同的表格中,你甚至可以使用完全不同的模型。
最后,你应该在面板 中激活应用身份验证恢复代码功能。为此,请在配置中的 multiFactorAuthentication() 方法中将 recovery() 方法传递给 AppAuthentication 实例:
use Filament\Auth\MultiFactor\App\AppAuthentication;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->multiFactorAuthentication([
AppAuthentication::make()
->recoverable(),
]);
}
修改恢复码的生成数量
默认情况下,Filament 为每位用户生成 8 个恢复码。如果你想修改,可以在配置的 multiFactorAuthentication() 方法中,使用 AppAuthentication 实例调用 recoveryCodeCount() 方法:
use Filament\Auth\MultiFactor\App\AppAuthentication;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->multiFactorAuthentication([
AppAuthentication::make()
->recoverable()
->recoveryCodeCount(10),
]);
}

