assghard/laravel-2fa

Laravel 2FA 包,提供通过电子邮件和短信发送验证码

1.0.0 2023-03-14 09:22 UTC

This package is auto-updated.

Last update: 2024-09-15 01:07:21 UTC


README

使用双因素认证保护用户账户。通过电子邮件或短信提供商发送2FA验证码。

如果您不使用Jetstream但需要2FA,此包很有帮助。

所有类都是可扩展的,因此您可以扩展和覆盖一切,并自定义和调整到项目中。没有特定的2FA概念或实现。此包仅提供一组有用的类和方法,因此您可以按自己的方式实现2FA。

功能

  • 定制化:包包含一套用于2FA验证的有用工具。您可以根据需要实现它们并自定义一切。每个类都可以扩展和覆盖。
  • 重发2FA码:每分钟一次
  • 灵活的配置
  • 每个码有效期为X分钟(config('2fa.user_code_valid_time'))。如果用户使用“重发”功能并接收N个码,则每个码的有效期均为X分钟。

要求

  • Laravel 8.x至9.x
  • PHP >= 8.0

Laravel和PHP支持

包尚未在较老版本的Laravel上测试

安装

安装和使用

  • 安装最新版本:运行 composer require assghard/laravel-2fa

    • 要安装旧版本,请运行: composer require assghard/laravel-2fa:VERSION
  • config -> app.php 的 providers 部分中添加提供者

'providers' => [
    TwoFactorVerificationServiceProvider::class,
]
  • 发布供应商: php artisan vendor:publish --provider="Assghard\Laravel2fa\TwoFactorVerificationServiceProvider" 此命令将向您的项目添加一些文件
config/2fa.php #2FA config

# migrations
migrations/create_user_2fa_codes_table.php
migrations/add_phone_number_field_to_users_table.php

# translations: add or delete languages you don't need
lang/en/2fa.php
lang/pl/2fa.php
  • 请记住,向 .env.env.example 文件中添加变量
# To enable 2FA for users
2FA_ENABLED=true

# uncomment if you are going to use sending 2FA SMS codes
# SMS_API_TOKEN=
# SMS_API_NAME_FORM=
  • 运行命令: php artisan migrate
  • 向您的用户模型添加内容
/*
 * =========================================
 * Basic usage
 * =========================================
 */

use Assghard\Laravel2fa\Traits\UserTwoFactorVerificationTrait; # Add trait in use section
use Assghard\Laravel2fa\Enums\TwoFactorVerificationMethodsEnum; # available 2FA methods Enum
...

class User extends Authenticatable implements MustVerifyEmail
{
    use UserTwoFactorVerificationTrait; // Use trait for 2FA
    ...

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [ # Add fillable fields
        ...
        'phone_number', # only if you are going to send 2FA codes via SMS message
    ];
  • 用户成功登录后发送2FA码。

App\Http\Controllers\Auth\AuthenticatedSessionController

use Assghard\Laravel2fa\Services\TwoFactorVerificationService;
use Assghard\Laravel2fa\Enums\TwoFactorVerificationMethodsEnum;
...
class AuthenticatedSessionController extends Controller
{
    ...

    $sent = (new TwoFactorVerificationService())->sendUserTwoFactorVerificationCode($user, $verificationMethodFromEnum);
    dd($sent);
    // And do everything you want after sending code
  • 您需要一个控制器: php artisan make:controller Auth\TwoFactroVerificationAuthController
  • 您还需要3个用于2FA验证的路由。将它们添加到Laravel的 auth.php 路由中。
    Route::middleware('auth')->group(function () {
        ...
        Route::group(['prefix' => '2fa'], function () {
            Route::get('verify', [TwoFactroVerificationAuthController::class, 'verify'])->name('2fa.verify');
            Route::post('verify', [TwoFactroVerificationAuthController::class, 'confirm'])->name('2fa.verify.confirm')->middleware('throttle:2fa_verify_confirm');
            Route::get('resend', [TwoFactroVerificationAuthController::class, 'resend'])->name('2fa.resend-code');
    });
  • 在项目的 RouteServiceProvider 中创建一个新的 2fa_verify_confirm 节流
    // 2fa_verify_confirm is a name of throttle and middleware
    RateLimiter::for('2fa_verify_confirm', function (Request $request) {
        return Limit::perMinute(5)->by($request->user()?->id ?: $request->ip());
    });
  • 可能需要中间件来检查代码是否已验证。

运行命令 php artisan make:middleware User2faCodeVerified

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class User2faCodeVerified
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
     */
    public function handle(Request $request, Closure $next)
    {
        // And do something like this or not :)
        // Database, session or other approach - the choice is yours

        $user = auth()->user();
        if ($user->two_factor_verification_codes()->count() > 0) {
            return redirect()->route('2fa.verify');
        }

如果您要将2FA方法分配给用户,并且用户(或管理员)可以更改方法(在这种情况下,请记住为 tfa_method 字段创建迁移)

/*
 * =========================================
 * NOT Basic usage (Example of customization)
 * =========================================
 */

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        ...
        'tfa_method' // 2FA method
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        ...
        'tfa_method' => TwoFactorVerificationMethodsEnum::class, // leverage enums for 2FA method casting
    ];

包组件

  • 迁移存根
  • 翻译
  • 模型
  • 枚举
  • 电子邮件和短信提供者
  • 特质
  • 通知提供者
  • 灵活的配置
    /**
     * Enable 2FA for Users. After enabling this feature 2FA will be required
     */
    'enabled' => env('2FA_ENABLED', false),

    /**
     * Default 2FA method
     * TwoFactorVerificationMethodsEnum::cases()
     */
    'default_method' => TwoFactorVerificationMethodsEnum::Email,

    /**
     * After successful login all user codes are deleting, so user will have limit reseted
     */
    'daily_user_codes_limit' => 25,

    /**
     * Single code valid time in minutes.
     * expires_at = now() + user_code_valid_time
     */
    'user_code_valid_time' => 10,

    'code' => [
        /**
         * Default 2FA code length
         */
        'length' => 6,
    
        /**
         * Default 2FA code length
         */
        'use_letters' => false,
    ],

    /**
     * SMS API config
     */
    'sms' => [
        /**
         * API token from https://www.smsapi.com/en
         */
        'api_token' => env('SMS_API_TOKEN', null),

        /**
         * Sender name
         */
        'name_from' => env('SMS_API_NAME_FORM', null),
    ],

待办事项列表

  • 测试
  • 重构
  • 测试
  • 将用户IP地址字段添加到 user_2fa_codes 表中?使代码仅对特定IP地址有效?

错误和建议

如果您发现错误,请打开问题或fork此项目并创建拉取请求

许可证

MIT许可证(MIT)。有关更多信息,请参阅许可证文件