abdullahfaqeir/laravel-otp

v5.0.0 2024-03-30 21:36 UTC

This package is auto-updated.

Last update: 2024-08-30 22:29:04 UTC


README

Test Status Latest Stable Version Total Downloads Code Style Status

简介

大多数Web应用都需要一个OTP(一次性密码)或安全代码来验证用户。此包允许您使用用户友好的方法发送/重新发送并验证OTP以进行用户身份验证。

版本兼容性

基本用法

<?php

/**
 * Send OTP via SMS.
 */
OTP()->send('+989389599530');
// or
OTP('+989389599530');

/**
 * Send OTP via channels.
 */
OTP()->channel(['otp_sms', 'mail', \App\Channels\CustomSMSChannel::class])
     ->send('+989389599530');
// or
OTP('+989389599530', ['otp_sms', 'mail', \App\Channels\CustomSMSChannel::class]);

/**
 * Send OTP for specific user provider
 */
OTP()->useProvider('admins')
     ->send('+989389599530');

/**
 * Validate OTP
 */
OTP()->validate('+989389599530', 'token_123');
// or
OTP('+989389599530', 'token_123');
// or
OTP()->useProvider('users')
     ->validate('+989389599530', 'token_123');

安装

您可以通过composer安装此包

composer require abdullahfaqeir/laravel-otp

配置

下一步,让我们通过执行以下命令发布配置文件 config/otp.php

php artisan vendor:publish --provider="AbdullahFaqeir\OTP\ServiceProvider" --tag="config"

令牌存储

此包允许您将生成的OTP存储在cachedatabase驱动器上,默认为cache

您可以通过我们之前发布的配置文件更改首选驱动器

// config/otp.php

<?php

return [
    /**
    |Supported drivers: "cache", "database"
    */
    'token_storage' => 'cache',
];
缓存

注意,Laravel OTP包使用已配置的cache驱动器来存储令牌,如果您尚未配置或尚未计划配置,则可以使用database

数据库

这意味着迁移后,将创建一个表,您的应用程序需要存储验证令牌。

如果您为mobile电话或甚至otp_tokens表使用其他列名,您可以在配置文件中自定义它们的值

// config/otp.php

<?php

return [

    'mobile_column' => 'mobile',

    'token_table'   => 'otp_token',

    //...
];

根据token_storage配置,此包将创建一个令牌表。此外,将在您的users默认提供者)表中添加一个mobile列,以显示用户验证状态并存储用户的手机号码。

好的!现在您应该迁移数据库

php artisan migrate

注意:当您使用OTP登录用户时,请考虑除了mobile列之外的所有列都必须是可空的。因为,在验证OTP后,如果用户不存在,将创建一个用户记录。

用户提供者

您可能希望为不同类型的用户使用OTP。Laravel OTP允许您定义和管理您需要的多个用户提供者。为了设置,您应该打开config/otp.php文件并定义您的提供者

// config/otp.php

<?php

return [
    //...

    'default_provider' => 'users',

    'user_providers'  => [
        'users' => [
            'table'      => 'users',
            'model'      => \App\Models\User::class,
            'repository' => \AbdullahFaqeir\OTP\NotifiableRepository::class,
        ],

       // 'admins' => [
       //   'model'      => \App\Models\Admin::class,
       //   'repository' => \AbdullahFaqeir\OTP\NotifiableRepository::class,
       // ],
    ],

    //...
];

注意:您还可以更改默认存储库并替换您自己的存储库。但是,每个存储库都必须实现AbdullahFaqeir\OTP\Contracts\NotifiableRepositoryInterface接口。

模型准备

每个模型都必须实现AbdullahFaqeir\OTP\Contracts\OTPNotifiable并使用此AbdullahFaqeir\OTP\Concerns\HasOTPNotify特性

<?php

namespace App\Models;

use AbdullahFaqeir\OTP\Concerns\HasOTPNotify;
use AbdullahFaqeir\OTP\Contracts\OTPNotifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable implements OTPNotifiable
{
    use Notifiable;
    use HasOTPNotify;

    // ...
}

SMS客户端

您可以使用任何SMS服务来发送OTP消息(这取决于您的选择)。

为了通过此包发送通知,首先您需要实现AbdullahFaqeir\OTP\Contracts\SMSClient合同。此合同要求您实现sendMessage方法。

此方法将通过包含用户mobiletoken消息的AbdullahFaqeir\OTP\Notifications\Messages\MessagePayload对象返回您的SMS服务API结果

<?php

namespace App;

use AbdullahFaqeir\OTP\Contracts\SMSClient;
use AbdullahFaqeir\OTP\Notifications\Messages\MessagePayload;

class SampleSMSClient implements SMSClient
{
    public function __construct(protected SampleSMSService $SMSService)
    {
    }

    public function sendMessage(MessagePayload $payload): mixed
    {
        return $this->SMSService->send($payload->to(), $payload->content());
    }

    // ...
}

在上面的示例中,SMSService可以替换为您选择的SMS服务及其相应的方法。

接下来,您应该在配置文件中设置客户端包装类SampleSMSClient

// config/otp.php

<?php

return [

  'sms_client' => \App\SampleSMSClient::class,

  //...
];

实际示例

这里我们准备了一个实际示例。假设您将通过发送OTP来登录/注册客户

<?php

namespace App\Http\Controllers;

use App\Models\User;
use AbdullahFaqeir\OTP\Exceptions\InvalidOTPTokenException;
use AbdullahFaqeir\OTP\OTPBroker as OTPService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Throwable;

class AuthController
{
    public function __construct(private OTPService $OTPService)
    {
    }

    public function sendOTP(Request $request): JsonResponse
    {
        try {
            /** @var User $user */
            $user = $this->OTPService->send($request->get('mobile'));
        } catch (Throwable $ex) {
          // or prepare and return a view.
           return response()->json(['message'=>'An unexpected error occurred.'], 500);
        }

        return response()->json(['message'=>'A token has been sent to:'. $user->mobile]);
    }

    public function verifyOTPAndLogin(Request $request): JsonResponse
    {
        try {
            /** @var User $user */
            $user = $this->OTPService->validate($request->get('mobile'), $request->get('token'));

            // and do login actions...

        } catch (InvalidOTPTokenException $exception){
             return response()->json(['error'=>$exception->getMessage()],$exception->getCode());
        } catch (Throwable $ex) {
            return response()->json(['message'=>'An unexpected error occurred.'], 500);
        }

         return response()->json(['message'=>'Logged in successfully.']);
    }
}

自定义

通知默认通道自定义

为了发送OTP通知,有一个默认通道。但是,此包允许您使用自己的通知通道。为了替换,您应该在这里指定通道类

//config/otp.php
<?php
return [
    // ...

    'channel' => \AbdullahFaqeir\OTP\Notifications\Channels\OTPSMSChannel::class,
];

注意:如果您更改了默认的短信通道,则 sms_client 将成为可选配置。否则,您必须定义自己的短信客户端。

通知短信和电子邮件定制

OTP通知默认准备了一个适用于大多数应用的短信和电子邮件格式。然而,您可以自定义邮件/短信消息的构建方式。

要开始,请向 AbdullahFaqeir\OTP\Notifications\OTPNotification 通知提供的 toSMSUsing/toMailUsing 方法传递一个闭包。闭包将接收接收通知的模型实例以及用于验证的 token。通常,您应该从您的应用程序的 App\Providers\AuthServiceProvider 类的启动方法调用这些方法。

<?php

use AbdullahFaqeir\OTP\Notifications\OTPNotification;
use AbdullahFaqeir\OTP\Notifications\Messages\OTPMessage;
use Illuminate\Notifications\Messages\MailMessage;

public function boot()
{
    // ...

    // SMS Customization
    OTPNotification::toSMSUsing(fn($notifiable, $token) =>(new OTPMessage())
                    ->to($notifiable->mobile)
                    ->content('Your OTP Token is: '.$token));

    //Email Customization
    OTPNotification::toMailUsing(fn ($notifiable, $token) =>(new MailMessage)
            ->subject('OTP Request')
            ->line('Your OTP Token is: '.$token));
}

翻译

要发布翻译文件,您可以使用此命令

php artisan vendor:publish --provider="AbdullahFaqeir\OTP\ServiceProvider" --tag="lang"

您可以在提供的语言文件中进行自定义

// resources/lang/vendor/OTP/en/otp.php

<?php

return [
    'otp_token' => 'Your OTP Token is: :token.',

    'otp_subject' => 'OTP request',
];

测试

composer test

变更日志

有关最近更改的详细信息,请参阅 变更日志

贡献

有关详细信息,请参阅 贡献指南

安全

如果您发现任何安全问题,请发送电子邮件至 abdullahfaqeir.dev@gmail.com,而不是使用问题跟踪器。

许可

Laravel-OTP 在 MIT 许可下发布。有关详细信息,请参阅捆绑的 LICENSE 文件。

用 ❤️ 为您构建。