emargareten / two-factor-laravel
Laravel应用程序的双因素认证实现。
Requires
- php: ^8.0
- bacon/bacon-qr-code: ^2.0
- laravel/framework: ^9.0|^10.0|^11.0
- pragmarx/google2fa: ^7.0|^8.0.1
Requires (Dev)
- laravel/pint: ^1.6
- orchestra/testbench: ^8.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.0
README
Two-Factor-Laravel 是一个用于为您的 Laravel 应用程序实现双因素认证的软件包。
如果启用,用户将在认证过程中被要求输入一个六位数的数字令牌。此令牌使用基于时间的单次密码 (TOTP) 生成,可以从任何兼容 TOTP 的移动认证应用程序(如 Google Authenticator)获取。
您还可以通过 SMS/电子邮件发送当前的单次密码给用户。
安装
首先,使用 composer 将软件包安装到您的项目中
composer require emargareten/two-factor-laravel
接下来,您应该使用 vendor:publish
Artisan 命令发布配置和迁移文件
php artisan vendor:publish --provider="Emargareten\TwoFactor\ServiceProvider"
最后,您应该运行应用程序的数据库迁移。这将向 users
表添加双因素列
php artisan migrate
配置
发布资源后,您可能需要检查 config/two-factor.php
配置文件。此文件包含一些选项,允许您自定义双因素认证功能的行为。
用法
要开始使用双因素认证,您应该首先将 TwoFactorAuthenticatable
特性添加到您的 User
模型中
use Emargareten\TwoFactor\TwoFactorAuthenticatable; class User extends Authenticatable { use TwoFactorAuthenticatable; }
启用双因素认证
此软件包提供了使用双因素认证验证用户逻辑。然而,您需要提供启用和禁用双因素认证的用户界面和控制器的代码。
要为用户启用双因素认证,您应该在用户模型上调用 enableTwoFactorAuthentication
方法。这将生成用户的密钥和恢复码,并将它们存储在数据库中(加密)
use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; class TwoFactorAuthenticationController extends Controller { /** * Enable two-factor authentication for the user. */ public function store(Request $request): RedirectResponse { $user = $request->user(); if ($user->hasEnabledTwoFactorAuthentication()) { return back()->with('status', 'Two-factor authentication is already enabled'); } $user->enableTwoFactorAuthentication(); return redirect()->route('account.two-factor-authentication.confirm.show'); } }
确认双因素认证
启用双因素认证后,用户必须通过提供有效的双因素认证代码来“确认”他们的双因素认证配置。您应该提供一种方式让用户完成此操作。例如,您可以提供一个视图,显示用户可以扫描到他们的认证器应用程序中的二维码和密钥
use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\View\View; class TwoFactorAuthenticationConfirmationController extends Controller { /** * Get the two-factor authentication confirmation view. */ public function show(Request $request): View|RedirectResponse { $user = $request->user(); if ($user->hasEnabledTwoFactorAuthentication()) { return back()->with('status', 'Two-factor authentication is already enabled'); } if (! $user->two_factor_secret) { return back()->with('status', 'Two-factor authentication is not enabled'); } return view('account.two-factor-confirmation.show', [ 'qrCodeSvg' => $user->twoFactorQrCodeSvg(), 'setupKey' => $user->two_factor_secret, ]); } /** * Confirm two-factor authentication for the user. */ public function store(Request $request): RedirectResponse { $request->validate([ 'code' => ['required', 'string'], ]); $request->user()->confirmTwoFactorAuthentication($request->code); return redirect() ->route('account.two-factor-authentication.recovery-codes.index') ->with('status', 'Two-factor authentication successfully confirmed'); } }
如果您希望使用其他方法接收单次密码,例如 SMS/电子邮件,您可以使用用户模型上的 getCurrentOtp
方法检索当前的单次密码
$user->getCurrentOtp();
注意 当通过 SMS/电子邮件发送单次密码时,您应该将窗口设置为更高的值,以便用户可以在发送后输入单次密码。
confirmTwoFactorAuthentication
方法接受一个可选的第二个参数来指定双因素方法,这是完全可选的,如果您有多个接收单次密码的方法,这可能很有用。
禁用双因素认证
您还应提供一种方式让用户禁用双因素认证。这可以通过在用户模型上调用 disableTwoFactorAuthentication
方法来完成
/** * Disable two-factor authentication for the user. */ public function destroy(Request $request): RedirectResponse { $request->user()->disableTwoFactorAuthentication(); return back()->with('status', 'Two-factor authentication disabled successfully'); }
用户认证
一旦用户确认启用双因素认证,每次他们登录时,他们将被重定向到一个页面,要求他们输入由他们的认证器应用程序生成的单次密码。
use Emargareten\TwoFactor\Actions\TwoFactorRedirector; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; public function login(Request $request, TwoFactorRedirector $redirector): Response { // do login stuff... return $redirector->redirect($request); }
这会将用户重定向到 two-factor-challenge.create
路由。
如果用户正在被重定向到双因素挑战页面,将触发 TwoFactorAuthenticationChallenged
事件,您可以监听此事件来添加额外的逻辑,例如,您可以通过 SMS/电子邮件发送单次密码。
public function handle(TwoFactorAuthenticationChallenged $event): void { $event->user->notify(new CompleteSignInOTP); }
您需要为 two-factor-challenge.create
路由提供一个视图。这个视图应包含一个表单,用户可以在其中输入一次性密码,您应该通过调用 TwoFactor::challengeView()
方法,在 AppServiceProvider
的 register
方法中绑定视图。
/** * Register any application services. */ public function register(): void { TwoFactor::challengeView('two-factor-challenge.create'); }
或者使用闭包来生成自定义响应
TwoFactor::challengeView(function (Request $request) { return Inertia::render('TwoFactorChallenge/Create'); });
表单应提交到 two-factor-challenge.store
路由。
一旦用户输入了有效的一次性密码,他们将被重定向到预期的URL(如果没有设置预期URL,则重定向到配置文件中定义的首页路由)。
恢复码
此包还提供了生成和使用恢复码的逻辑。恢复码可以在用户失去对其认证应用的访问时用于访问应用。
在启用双因素认证后,您应将用户重定向到可以查看其恢复码的页面。您还可以通过在用户模型上调用 generateNewRecoveryCodes
方法来生成一组新的恢复码。
use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\View\View; class TwoFactorAuthenticationRecoveryCodeController extends Controller { /** * Get the two-factor authentication recovery codes for authenticated user. */ public function index(Request $request): View|RedirectResponse { if (! $request->user()->hasEnabledTwoFactorAuthentication()) { return back()->with('status', 'Two-factor authentication is disabled'); } return view('two-factor-recovery-codes.index', [ 'recoveryCodes' => $request->user()->two_factor_recovery_codes, ]); } /** * Generate a fresh set of two-factor authentication recovery codes. */ public function store(Request $request): RedirectResponse { if (! $request->user()->hasEnabledTwoFactorAuthentication()) { return back()->with('status', 'Two-factor authentication is disabled'); } $request->user()->generateNewRecoveryCodes(); return redirect()->route('account.two-factor-authentication.recovery-codes.index'); } }
要使用恢复码,您应在 two-factor-challenge-recovery.create
路由中添加一个视图。这个视图应包含一个表单,用户可以在其中输入恢复码。您应该通过调用 TwoFactor::challengeRecoveryView()
方法,在 AppServiceProvider
的 register
方法中绑定视图。
表单应提交到 two-factor-challenge-recovery.store
路由。
测试
composer test
变更日志
请参阅变更日志获取有关最近更改的更多信息。
致谢
许可证
MIT许可证(MIT)。请参阅许可证文件获取更多信息。