В этой статье я расскажу о том, как войти в систему с помощью OTP в LARAVEL 9.
После установки Laravel и Laravel Authentication откройте проект кода в редакторе кода & выполните следующие шаги.
Шаг — 1
Добавьте номер мобильного телефона в таблицу users
.
Чтобы добавить столбец, создайте Migration, выполнив команду ниже.
php artisan make:migration add_mobile_no_in_users_table
Команда создаст файл в папке database/migrations
, откройте файл миграции и обновите приведенный ниже код.
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('mobile_no')->nullable()->after('username');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('mobile_no');
});
}
};
Теперь запустите миграцию командой, она добавит номер мобильного телефона в таблицу пользователей.
php artisan migrate
Теперь обновите app/Http/Controllers/Auth/RegisterController.php
для регистрации пользователя с номером мобильного телефона.
<?php
namespace AppHttpControllersAuth;
use AppHttpControllersController;
use AppProvidersRouteServiceProvider;
use AppModelsUser;
use IlluminateFoundationAuthRegistersUsers;
use IlluminateSupportFacadesHash;
use IlluminateSupportFacadesValidator;
class RegisterController extends Controller
{
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return IlluminateContractsValidationValidator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'username' => ['required', 'string', 'max:255'],
'mobile_no' => ['required', 'number', 'max:10'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return AppModelsUser
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'username' => $data['username'],
'mobile_no' => $data['mobile_no'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}
Затем обновите ‘resources/views/auth/register.blade.php’ и обновите код ниже.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Register') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('register') }}">
@csrf
<div class="row mb-3">
<label for="name" class="col-md-4 col-form-label text-md-end">{{ __('Name') }}</label>
<div class="col-md-6">
<input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>
@error('name')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-3">
<label for="username" class="col-md-4 col-form-label text-md-end">{{ __('Username') }}</label>
<div class="col-md-6">
<input id="username" type="text" class="form-control @error('username') is-invalid @enderror" name="username" value="{{ old('username') }}" required autocomplete="username" autofocus>
@error('username')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-3">
<label for="mobile_no" class="col-md-4 col-form-label text-md-end">{{ __('Mobile No') }}</label>
<div class="col-md-6">
<input id="mobile_no" type="text" class="form-control @error('mobile_no') is-invalid @enderror" name="mobile_no" value="{{ old('mobile_no') }}" required autocomplete="mobile_no" autofocus>
@error('mobile_no')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-3">
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email">
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-3">
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-3">
<label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label>
<div class="col-md-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
</div>
</div>
<div class="row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Register') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Форма регистрации будет выглядеть следующим образом.
Шаг — 2
Создайте модель VerificationCode с миграцией, выполнив команду ниже.
php artisan make:model VerificationCode -m
Эта команда создаст модель VerificationCode в папке app/models
и миграцию в database/migrations
.
Давайте откроем модель VerificationCode из app/Models/VerificationCode.php
и обновим ее с помощью кода ниже.
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class VerificationCode extends Model
{
use HasFactory;
protected $fillable = ['user_id', 'otp', 'expire_at'];
}
Теперь обновим миграцию таблицы verification_codes
, откройте файл из database/migrations
и обновите код ниже.
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('verification_codes', function (Blueprint $table) {
$table->id();
$table->bigInteger('user_id');
$table->string('otp');
$table->timestamp('expire_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('verification_codes');
}
};
Далее запустите миграцию для создания таблицы verification_codes
.
php artisan migrate
Шаг — 3
Создайте AuthOtpController, выполнив команду
php artisan make:controller AuthOtpController
Этот контроллер будет обрабатывать все операции, связанные с аутентификацией с помощью OTP.
Откройте контроллер из app/Http/Controllers/AuthOtpController.php
& Обновите контроллер с помощью приведенного ниже кода.
<?php
namespace AppHttpControllers;
use CarbonCarbon;
use AppModelsUser;
use IlluminateHttpRequest;
use AppModelsVerificationCode;
use IlluminateSupportFacadesAuth;
class AuthOtpController extends Controller
{
// Return View of OTP Login Page
public function login()
{
return view('auth.otp-login');
}
// Generate OTP
public function generate(Request $request)
{
# Validate Data
$request->validate([
'mobile_no' => 'required|exists:users,mobile_no'
]);
# Generate An OTP
$verificationCode = $this->generateOtp($request->mobile_no);
$message = "Your OTP To Login is - ".$verificationCode->otp;
# Return With OTP
return redirect()->route('otp.verification', ['user_id' => $verificationCode->user_id])->with('success', $message);
}
public function generateOtp($mobile_no)
{
$user = User::where('mobile_no', $mobile_no)->first();
# User Does not Have Any Existing OTP
$verificationCode = VerificationCode::where('user_id', $user->id)->latest()->first();
$now = Carbon::now();
if($verificationCode && $now->isBefore($verificationCode->expire_at)){
return $verificationCode;
}
// Create a New OTP
return VerificationCode::create([
'user_id' => $user->id,
'otp' => rand(123456, 999999),
'expire_at' => Carbon::now()->addMinutes(10)
]);
}
public function verification($user_id)
{
return view('auth.otp-verification')->with([
'user_id' => $user_id
]);
}
public function loginWithOtp(Request $request)
{
#Validation
$request->validate([
'user_id' => 'required|exists:users,id',
'otp' => 'required'
]);
#Validation Logic
$verificationCode = VerificationCode::where('user_id', $request->user_id)->where('otp', $request->otp)->first();
$now = Carbon::now();
if (!$verificationCode) {
return redirect()->back()->with('error', 'Your OTP is not correct');
}elseif($verificationCode && $now->isAfter($verificationCode->expire_at)){
return redirect()->route('otp.login')->with('error', 'Your OTP has been expired');
}
$user = User::whereId($request->user_id)->first();
if($user){
// Expire The OTP
$verificationCode->update([
'expire_at' => Carbon::now()
]);
Auth::login($user);
return redirect('/home');
}
return redirect()->route('otp.login')->with('error', 'Your Otp is not correct');
}
}
Шаг — 4
Создайте маршруты для OTP логина и верификации, откройте routes/web.php
и обновите код внизу.
Route::controller(AuthOtpController::class)->group(function(){
Route::get('/otp/login', 'login')->name('otp.login');
Route::post('/otp/generate', 'generate')->name('otp.generate');
Route::get('/otp/verification/{user_id}', 'verification')->name('otp.verification');
Route::post('/otp/login', 'loginWithOtp')->name('otp.getlogin');
});
Шаг — 5
Создайте файлы представлений в папке resources/views/auth
,
Сначала создайте otp-login.blade.php
и введите код ниже.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('OTP Login') }}</div>
<div class="card-body">
@if (session('error'))
<div class="alert alert-danger" role="alert"> {{session('error')}}
</div>
@endif
<form method="POST" action="{{ route('otp.generate') }}">
@csrf
<div class="row mb-3">
<label for="mobile_no" class="col-md-4 col-form-label text-md-end">{{ __('Mobile No') }}</label>
<div class="col-md-6">
<input id="mobile_no" type="text" class="form-control @error('mobile_no') is-invalid @enderror" name="mobile_no" value="{{ old('mobile_no') }}" required autocomplete="mobile_no" autofocus placeholder="Enter Your Registered Mobile Number">
@error('mobile_no')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Generate OTP') }}
</button>
@if (Route::has('login'))
<a class="btn btn-link" href="{{ route('login') }}">
{{ __('Login With Username') }}
</a>
@endif
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Теперь создайте другой файл представления otp-verification.blade.php
& обновите код ниже.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('OTP Login') }}</div>
<div class="card-body">
@if (session('success'))
<div class="alert alert-success" role="alert"> {{session('success')}}
</div>
@endif
@if (session('error'))
<div class="alert alert-danger" role="alert"> {{session('error')}}
</div>
@endif
<form method="POST" action="{{ route('otp.getlogin') }}">
@csrf
<input type="hidden" name="user_id" value="{{$user_id}}" />
<div class="row mb-3">
<label for="mobile_no" class="col-md-4 col-form-label text-md-end">{{ __('OTP') }}</label>
<div class="col-md-6">
<input id="otp" type="text" class="form-control @error('otp') is-invalid @enderror" name="otp" value="{{ old('otp') }}" required autocomplete="otp" autofocus placeholder="Enter OTP">
@error('otp')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Login') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Полный поток будет выглядеть следующим образом.
Откройте проект и перейдите к /otp/login
и он будет выглядеть следующим образом.
Как только вы введете зарегистрированный номер мобильного телефона, он перенаправит вас на экран верификации с OTP во флэш-сообщении.
После того, как вы введете OTP, он войдет в систему и перенаправит вас на приборную панель.
Надеюсь, это поможет вам войти в систему с помощью OTP
в LARAVEL 9.
Полный видеоурок на YouTube.
Если у вас возникнут какие-либо проблемы при внедрении, пожалуйста, прокомментируйте ваш вопрос.
Спасибо за прочтение
Свяжитесь со мной.
Twitter
Instagram
YouTube