cuongnd88/otp-auth
Composer 安装命令:
composer require cuongnd88/otp-auth
包简介
Laravel OTP Authentication (One Time Passwords)
README 文档
README
This package allows you to authenticate with one time password access (OTP).
Example Usage:
Route::get("/notify", function(){ return App\Models\User::find(1)->notify(new App\Authentication\SendOtp('mail', 4, 10)); }); Route::get("/auth-otp/{otp}", function(){ return App\Models\User::authByOtp(request()->otp, '84905.......'); }); Route::get("/check-otp/{otp}", function(){ return App\Models\User::find(1)->checkOtp(request()->otp); });
Contents
Installation
1- Add the package to your dependencies.
$ composer require cuongdinhngo/otp-auth
2- Run the command:
php artisan auth:otp {ClassName}
Example:
php artisan auth:otp Authentication/SendOtp
SendOtp class and HasOtpAuth trait are auto-generated at app/Authentication directory.
CreateNotificationsTable class is alseo auto-generated at app/database/migrations.
3- Apply the migrations:
It will create a table called notifications to store generated OTP information.
$ php artisan migrate
Usage
Generate OTP
You can generate OTP via email or SMS
Route::get("/notify", function(){ return App\Models\User::find(1)->notify(new App\Authentication\SendOtp(['mail', 'nexmo'])); });
This package allows you to alter OTP length and lifetime
Route::get("/notify", function(){ $length = 4; $liftime = 10; //minutes return App\Models\User::find(1)->notify(new App\Authentication\SendOtp(['mail', 'nexmo']), $length, $liftime); });
OTP default length: The default length is 6.
OTP default lifetime: The default lifetime is 1 minute.
There is the detail of auto-generate SentOTP class:
<?php namespace App\Authentication; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; use Cuongnd88\DeliveryChannel\Messages\TwilioMessage; class SendOtp extends Notification { use Queueable; protected $defaultChannels = ['database']; protected $otp; protected $lifeTime; const OPT_LIFETIME = 1; const OPT_LENGTH = 6; /** * Construct * * @param array|string $channels * @param integer|string $otpLength * @param integer|string $lifeTime */ public function __construct($channels = null, $otpLength = null, $lifeTime = null) { $this->otp = $this->generateOtp($otpLength ?? self::OPT_LENGTH); $this->lifeTime = $lifeTime ?? self::OPT_LIFETIME; $this->defaultChannels = $this->verifyChannels($channels); } /** * Get the notification's delivery channels. * * @param mixed $notifiable * @return array */ public function via($notifiable) { return $this->defaultChannels; } /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { return (new MailMessage) ->line('Your OTP is '.$this->otp) ->line('Thank you for using our application!'); } /** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toArray($notifiable) { return [ 'otp' => $this->otp, 'expired_at' => now()->addMinutes($this->lifeTime)->toDateTimeString(), ]; } /** * Get the Nexmo / SMS representation of the notification. * * @param mixed $notifiable * * @return mixed */ public function toTwilio($notifiable) { return (new TwilioMessage) ->to("+8439xxxxxxx") ->from("+xxxxxxxxxx") ->body('OTP AUTH is '.$this->otp); } /** * Generate OTP * * @param integer|string $n * * @return string */ public function generateOtp($n) { $generator = "09xxxxxxx"; $result = ""; for ($i = 1; $i <= $n; $i++) { $result .= substr($generator, (rand()%(strlen($generator))), 1); } return $result; } /** * Verify channels * * @param string|array $channels * * @return array */ public function verifyChannels($channels) { if ($channels && is_array($channels)) { return array_merge($this->defaultChannels, $channels); } if ($channels && is_string($channels)) { array_push($this->defaultChannels, $channels); } return $this->defaultChannels; } }
toTwilio: This method is implemented by importing delivery-channels.
Verify OTP
After sent OTP via your configed methods, you call authByOtp to authenticate
Route::get("/auth-otp/{otp}", function(){ return App\Models\User::authByOtp(request()->otp, '84905123456'); });
Based on your credentials, you might authenticate with email or phone number
Set up the credentials:
In this case, you can apply User model which must use HasOtpAuth trait
. . . . use App\Authentication\HasOtpAuth; class User extends Authenticatable { use Notifiable; use HasOtpAuth; protected $credential = 'mobile'; . . . .
Let see more detail HasOtpAuth trait
<?php namespace App\Authentication; trait HasOtpAuth { /** * Check OTP * * @return bool */ public function checkOtp($otp) { $authenticator = $this->otp(); return $this->validateOtp($authenticator, $otp); } /** * Get OTP data * * @return \Illuminate\Notifications\DatabaseNotification */ public function otp() { return $this->notifications() ->where('type', 'LIKE', '%SendOtp%') ->whereNull('read_at') ->first(); } /** * Validate OTP * * @param \Illuminate\Notifications\DatabaseNotification $authenticator * @param mixed $otp * * @return void */ public function validateOtp($authenticator, $otp) { $result = false; if (is_null($authenticator)) { return response()->json($result,200); } if ($authenticator && now()->lte($authenticator->data['expired_at']) && $authenticator->data['otp'] == $otp ) { $result = true; } $authenticator->markAsRead(); return response()->json($result,200); } /** * Authenticate by OTP * * @param string $otp * @param string $credentialValue * @return void */ public static function authByOtp($otp, $credentialValue) { $model = new static; $credentialName = property_exists($model,'credential') ? $model->credential : 'email'; $authenticator = $model->where($credentialName, '=', $credentialValue)->first(); if (is_null($authenticator)) { return response()->json(false,200); } $authenticator = $authenticator->notifications() ->where('type', 'LIKE', '%SendOtp%') ->whereNull('read_at') ->first(); return $model->validateOtp($authenticator, $otp); } }
Basic identification
In some cases, you just need to identify the right access, you might need to execute checkOtp method
Route::get("/check-otp/{otp}", function(){ return auth()->user->checkOtp(request()->otp); });
Demo
This is demo soure code. Laravel Colab
Credits
- Ngo Dinh Cuong
cuongnd88/otp-auth 适用场景与选型建议
cuongnd88/otp-auth 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 528 次下载、GitHub Stars 达 10, 最近一次更新时间为 2021 年 06 月 10 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「Authentication」 「laravel」 「otp」 「one time passwords」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 cuongnd88/otp-auth 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 cuongnd88/otp-auth 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 cuongnd88/otp-auth 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Automatically logs-in users if they are already authenticated by a remote source. (e.g. environment variable REMOTE_USER)
GraphQL authentication for your headless Craft CMS applications.
Laravel middleware to restrict a site or specific routes using HTTP basic authentication
Email Toolkit Plugin for CakePHP
OTP generating package
A list of dangerous usernames
统计信息
- 总下载量: 528
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 10
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2021-06-10