用于在Laravel中构建两步验证

安装: 44

依赖项: 0

建议者: 0

安全: 0

星标: 0

关注者: 1

分支: 0

公开问题: 0

类型:laravel-package

v2.0.0 2024-04-25 13:25 UTC

This package is auto-updated.

Last update: 2024-09-25 14:42:59 UTC


README

这是一个Laravel两步验证包,默认通过电子邮件提供两步验证,但也支持TOTP(基于时间的单次密码)以用于Microsoft Authenticator和Google Authenticator等身份验证器应用程序。类可以被覆盖,功能可以完全自定义,允许您为用户提供两步验证。添加两步验证就像将路由中间件"twofactor"分配给如下示例所示一样简单。

  Route::group(['middleware' => ['auth','twofactor:always']], function () {
        // Sales Routes
        Route::get('user/orders', 'Backend\IncomeController@index')->name('user.orders');
  });

您可以为"always"标签提供,即使用户没有启用两步验证,也始终要求两步验证。您可以为"if-enabled"标签提供,在这种情况下,只有当用户启用了两步验证时,才会进行两步验证。当用户完成两步验证后,它将在其账户上启用。

安装DragonZAP2FA包

您已经看到了使用此包有多简单,现在让我们开始安装。首先安装Composer,它将允许您安装我们的包。Composer安装完成后,您必须在Laravel目录中运行以下命令

composer install dragonzap/2fa ^2.0

发布供应商文件

接下来,您需要发布供应商文件

php artisan vendor:publish --provider="Dragonzap\TwoFactorAuthentication\TwoFactorAuthenticationProvider" 

迁移数据库

完成这些更改后,现在您需要迁移Laravel数据库

php artisan migrate

这将确保对用户表的更改生效,以允许为用户启用或禁用两步验证

更改配置

完成所有这些步骤后,包已安装,您可以在./config/dragonzap_2fa.php中找到并自定义配置文件

<?php

/*
 * Licensed under GPLv2
 * Author: Daniel McCarthy
 * Dragon Zap Publishing
 * Website: https://dragonzap.com
 */

<?php

/*
 * Licensed under GPLv2
 * Author: Daniel McCarthy
 * Dragon Zap Publishing
 * Website: https://dragonzap.com
 */

 
return [
   'enabled' => env('DRAGONZAP_2FACTOR_ENABLED', true),
   'totp' => [
       'issuer' => env('DRAGONZAP_2FACTOR_TOTP_ISSUER', 'MyExampleApp'),
       'model' => \Dragonzap\TwoFactorAuthentication\Models\TwoFactorTotp::class,
       'messages' => [
        'check_code' => 'Please check your authenticator app for the code.',
        'invalid_authenticator' => 'Misconfigured authenticator contact support',
        'code_invalid' => 'The code is invalid or expired.',
        'no_code_provided' => 'No code was provided.',
        'code_incorrect' => 'The code is incorrect.',
        'wrong_2fa_type' => 'A different two factor type is required for this user account.',
        'no_totp_id_provided' => 'No TOTP ID was provided.',
        'invalid_totp_id' => 'Invalid TOTP ID provided.',
       ]
   ],
   'authentication' => [
       'expires_in_minutes' => env('DRAGONZAP_2FACTOR_AUTHENTICATION_EXPIRES_IN_MINUTES', 15),
       'handler' => [
        // This is the authentication handler class, you can override your own class here
        // if you wish to have custom functionality
        'class' => \Dragonzap\TwoFactorAuthentication\TwoFactorAuthenticationHandler::class,
       ]
   ],
   'messages' => [
    'code_sent' => 'A code has been sent to you. Please enter it below.',
    'code_invalid' => 'The code is invalid or expired.',
    'no_code_provided' => 'No code was provided.',
    'code_incorrect' => 'The code is incorrect.',
    'wrong_2fa_type' => 'A different two factor type is required for this user account.',
   ],
   'notification' => [
    // You can change the notification subject for the TwoFactorCodeNotification class here
    'subject' => 'Confirm your two factor authentication code',
    // For more customization options, you can create your own notification class and set it here
    // Allowing you to extend to sms messages, slack, etc.
    'class' => \Dragonzap\TwoFactorAuthentication\Notifications\TwoFactorCodeNotification::class,
   ],
   
];

这些设置允许您更改消息、通知类以及两步验证在保护页面需要再次启用之前将保持多久

不同的路由中间件

  • "twofactor:always" 对于给定的路由,将要求进行身份验证,无论用户是否启用了2FA,一旦认证成功,2FA将自动为用户的账户启用。可以通过扩展TwoFactorAuthenticationHandler类并重写authenticationCompleted方法来修改功能。然后更新配置文件中的处理器类。
  • "twofactor:if-enabled" 只有当用户启用了两步验证时,才会要求给定的路由进行身份验证。
  • "twofactor:only-once-if-enabled" 如果应用于路由,则在整个用户会话中,只有在首次访问该路由时才要求进行身份验证。用户可以在任何路由上进行认证以通过此检查,只要他们在当前会话中已对任何路由进行了认证。如果用户没有启用2FA,则不需要进行认证。
  • "twofactor:only-once-always"twofactor:only-once-if-enabled 类似,但无论用户是否启用了2FA,都会要求所有用户进行认证。一旦认证成功,2FA将为其用户账户启用。

在用户账户上启用两步验证

要在用户账户上启用两步验证,将"two_factor_enabled"列设置为给定用户记录的true。

编辑视图

您可以在views/vendor/dragonzap目录中找到视图,您可以在其中修改允许用户输入两步验证码的blade文件。

管理用户两步验证设置的示例控制器

该软件包仅管理双因素认证进行授权,没有提供控制器以允许在用户账户上启用双因素认证。请参考以下示例控制器了解如何实现。可以看出,此软件包创建的用户表中的两列:two_factor_enabled 和 two_factor_type。您可以通过修改这些值来为您的用户启用双因素认证。

<?php

namespace App\Http\Controllers\Backend\Auth\User;

use App\Http\Controllers\Controller;
use Dragonzap\TwoFactorAuthentication\TwoFactorAuthentication;
use Illuminate\Http\Request;


/**
 * Class AccountController.
 */
class TwoFactorAuthenticationController extends Controller
{
    public function updateTwoFactorAuthenticationEnabled(Request $request)
    {
        $user = auth()->user();

        if ($request->has('two_factor_enabled') && $request->get('two_factor_enabled') == '1'){
            $user->two_factor_enabled = true;
            $user->save();

            return redirect()->route('admin.account')->withFlashSuccess(__('Two Factor Authentication has been enabled.'))->with('tab', 'two-factor-auth');
        }

        $user->two_factor_enabled = false;
        $user->save();

        return redirect()->back()->withFlashSuccess( __('Two Factor Authentication has been disabled your account is no longer secure.'))->with('tab', 'two-factor-auth');
    }

    public function changeTwoFactorAuthenticationType(Request $request)
    {
        $user = auth()->user();

        if ($request->has('two_factor_type') && $request->get('two_factor_type') == 'totp'){
            $user->two_factor_type = 'totp';
            $user->save();

            // Generate a new TOTP for this user and delete old TOTPS
            TwoFactorAuthentication::generateTotpForUser(auth()->user(), NULL, true);

            return redirect()->route('admin.account')->withFlashSuccess(__('Two Factor Authentication type has been changed to TOTP.'))->with('tab', 'two-factor-auth');
        }

        $user->two_factor_type = 'otp';
        $user->save();

        return redirect()->route('admin.account')->withFlashSuccess(__('Two Factor Authentication type has been changed to email codes.'))->with('tab', 'two-factor-auth');
    }

    public function confirmTOTPAuthentication(Request $request)
    {
        $user = auth()->user();

        if ($request->has('code')){
            $totp = TwoFactorAuthentication::getTotpsForUser($user)->first();
            // By veryfing the code correctly we are also confirming the TOTP, making it active
            // after the first use which is now it becomes a valid TOTP
            if ($totp && $totp->verify($request->get('code'))){
                return redirect()->route('admin.account')->withFlashSuccess(__('Two Factor Authentication has been confirmed do not lose your authenticator app!'))->with('tab', 'two-factor-auth');
            }
        }

        // Return error for the code field, affecting the errors bundle
        return redirect()->route('admin.account')->withErrors(['code' => __('The code you entered is invalid.')])->with('tab', 'two-factor-auth');
    }
}

认证类型

当 two_factor_enabled 列为 true 时,用户表中的 two_factor_type 列确定应与用户一起使用的双因素认证类型。

  • otp - 这是老式的OTP,默认情况下会发送电子邮件给用户,除非此功能被覆盖。
  • totp - 这是现代的TOTP,需要使用认证器应用程序,将用户的 two_factor_type 列设置为 totp 以要求该用户使用认证器应用程序。

已确认TOTP与未确认TOTP

当使用 TwoFactorAuthentication::generateTotpForUser 方法生成TOTP时,生成的TOTP将处于不活跃的未确认状态。如果用户已将 two_factor_type 设置为 "totp" 以表示需要认证应用程序,但尚未确认TOTP代码,则认证请求将切换到 "otp",默认发送电子邮件给用户。只有在TOTP被确认后,用户才会被提示在认证应用程序中输入代码。这可以防止用户启用TOTP并忘记扫描QR代码,导致他们被锁定在自己的账户之外,因此作为预防措施,此场景下将默认使用OTP。

如何确认TOTP?

可以通过将关联用户账户的特定模型记录 TwoFactorTotp 中的 "confirmed" 列设置为 true 来确认TOTP。您应在用户证明他们已扫描QR代码后仅确认TOTP。为了证明用户已这样做,您可以要求他们在认证应用程序中输入代码并验证它。在验证TOTP代码后,记录将自动更新为已确认状态,确保TOTP用于所有未来的认证。

确认TOTP的示例代码

// Get the first TOTP associated with the user account, users can have many TOTPs
      $totp = TwoFactorAuthentication::getTotpsForUser($user)->first();
      // Call the verify funnction 
            if ($totp && $totp->verify($request->get('code'))){
                return redirect()->route('admin.account')->withFlashSuccess(__('Two Factor Authentication has been confirmed do not lose your authenticator app!'))->with('tab', 'two-factor-auth');
            }

在调用 verify 方法时,如果验证正确,TOTP记录中的 confirmed 列将设置为 true,允许此TOTP用于所有未来的认证。