Laravel 9 2FA - Authy를 사용한 이중 인증
70660 단어 javascriptlaravel2falaraveltutorial
https://codeanddeploy.com/blog/laravel/laravel-9-2fa-two-factor-authentication-with-authy
이 게시물에서는 Authy를 사용하여 Laravel 8, 9 2FA - 2단계 인증을 구현하는 방법을 공유할 것입니다. 우리는 2단계 인증이 다른 사람이 사용자 자격 증명을 얻고 계정에 액세스하는 경우 애플리케이션 보안의 추가 계층이라는 것을 알고 있습니다. 이 구현을 사용하면 인증을 계속하기 전에 다른 확인이 필요하기 때문에 사용자 계정에 액세스하는 것이 확실히 쉽지 않을 것입니다.
이 튜토리얼에서는 Laravel Two Factor 인증을 위해 Authy 앱을 사용하고 이를 수행하는 방법을 단계별로 보여드리겠습니다.
시작하기 전에 프로세스를 단축할 수 있도록 Laravel 9 인증에 대한 이전 튜토리얼을 다운로드해야 합니다. 그러나 Laravel 인증이 이미 있는 경우 이를 건너뛰고 Laravel Two Factor Authentication을 직접 구현할 수 있습니다.
인증에 대한 이전 자습서here를 방문하십시오.
이제 시작하겠습니다.
1단계. 라라벨 2단계 구성 설정
ENV를 사용하여 다음 코드를 추가합니다.
AUTHY_KEY=YOUR API KEY HERE
Authy 애플리케이션을 만드는 것을 잊지 마십시오.
이 구성에서는 나중에 A
uthy Application API
키를 추가해야 합니다.그런 다음 완료되면 다음 배열 값을
config/services.php
에 추가하십시오.'authy' => [
'key' => env('AUTHY_KEY')
]
2단계: 작성기를 통해 인증 설치
composer.json
내부에 JSON 값이 필요하면 다음 줄을 추가합니다."authy/php": "^4.0"
다음과 같아야 합니다.
"require": {
"php": "^8.0.2",
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^9.2",
"laravel/sanctum": "^2.14.1",
"laravel/tinker": "^2.7",
"authy/php": "^4.0"
},
그런 다음 아래의 다음 명령을 실행합니다.
composer update
3단계: Authy Two Factor 열을 사용자 테이블에 추가
다음 명령을 실행합니다.
php artisan make:migration add_authy_columns_to_users_table
다음은 마이그레이션의 최종 코드입니다.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('authy_status')->nullable()->after('password');
$table->string('authy_id', 25)->after('authy_status');
$table->string('authy_country_code', 10)->after('authy_id');
$table->string('authy_phone')->after('authy_country_code');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('authy_status');
$table->dropColumn('authy_id', 25);
$table->dropColumn('authy_country_code', 10);
$table->dropColumn('authy_phone');
});
}
};
그럼 일단 완료. 다음 명령을 실행하십시오.
php artisan migrate
4단계: 사용자 모델 채울 수 있는 값 설정 및 2단계 확인
아래는 최종 코드입니다.
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'username',
'password',
'authy_status',
'authy_id',
'authy_country_code',
'authy_phone'
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
'authy_id'
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* Always encrypt password when it is updated.
*
* @param $value
* @return string
*/
public function setPasswordAttribute($value)
{
$this->attributes['password'] = bcrypt($value);
}
/**
* Check if factor enabled
*
* @return boolean
*/
public function isTwoFactorEnabled()
{
return $this->authy_status == 1 ? true : false;
}
}
5단계: Authy에 대한 서비스 클래스 추가
이제
Authy.php
탐색App/Services
폴더에 대한 서비스 클래스를 추가한 다음 TwoFactor
폴더를 추가하겠습니다. 완료되면 Authy.php
파일 생성 후 다음 코드를 추가합니다.<?php
namespace App\Services\TwoFactor;
class Authy {
/**
* @var \Authy\AuthyApi
*/
private $api;
public function __construct()
{
$this->api = new \Authy\AuthyApi(config('services.authy.key'));
}
/**
* @param $email
* @param $phoneNumber
* @param $countryCode
* @return int
* @throws \Exception
*/
function register($email, $phoneNumber, $countryCode)
{
$user = $this->api->registerUser($email, $phoneNumber, $countryCode);
return $user;
}
/**
* @param $authyId
* @return bool
* @throws \Exception
*/
public function sendToken($authyId)
{
$response = $this->api->requestSms($authyId);
return $response;
}
/**
* @param $authyId
* @param $token
* @return bool
* @throws \Exception Nothing will be thrown here
*/
public function verifyToken($authyId, $token)
{
$response = $this->api->verifyToken($authyId, $token);
return $response;
}
/**
* @param $authyId
* @return \Authy\value status
* @throws \Exception if request to api fails
*/
public function verifyUserStatus($authyId) {
$response = $this->api->userStatus($authyId);
return $response;
}
}
6단계: 프로필 컨트롤러 및 경로 설정
이제 다음 명령을 실행하여 ProfileController를 생성해 보겠습니다.
php artisan make:controller ProfileController
그런 다음 아래에 다음 코드를 추가합니다.
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use App\Services\TwoFactor\Authy;
class ProfileController extends Controller
{
protected $users;
protected $authy;
public function __construct(User $users, Authy $authy)
{
$this->users = $users;
$this->authy = $authy;
}
public function index()
{
return view('profile.index');
}
public function enableTwoFactor(Request $request)
{
$user = auth()->user();
$checkUser = User::where('authy_country_code', $request->get('country_code'))
->where('authy_phone', $request->get('phone_number'))
->first();
if(is_null($checkUser)) {
$register = $this->authy->register(
$user->email,
$request->get('phone_number'),
$request->get('country_code')
);
if ($register->ok()) {
$authyId = $register->id();
$user->update([
'authy_status' => false,
'authy_id' => $authyId,
'authy_country_code' => $request->get('country_code'),
'authy_phone' => $request->get('phone_number')
]);
} else {
return redirect('profile')->with('authy_errors', $register->errors());
}
} else {
$authyId = $checkUser->authy_id;
}
$this->authy->sendToken($authyId);
return redirect('profile/two-factor/verification');
}
public function disableTwoFactor(Request $request)
{
$user = auth()->user();
$user->update([
'authy_status' => false
]);
return redirect('profile')
->with('success', __('Two factor authentication has been disabled.'));
}
public function getVerifyTwoFactor()
{
return view('profile.verify-two-factor');
}
public function postVerifyTwoFactor(Request $request)
{
$user = auth()->user();
$verfiy = $this->authy->verifyToken($user->authy_id, $request->get('authy_token'));
if ( $verfiy->ok() ) {
$user->update(['authy_status' => 1]);
return redirect('profile')
->with('success', __('Two factor authentication has been enabled.'));
}
return redirect('profile/two-factor/verification')
->with('errors', __('Invalid token. Please try again.'));
}
}
P
rofileController
기능은 2요소 활성화, 2요소 비활성화, 추가 시 2요소 확인으로 구성됩니다.그런 다음 프로필 경로를 설정해 보겠습니다.
Route::group(['middleware' => ['auth']], function() {
/**
* Profile Routes
*/
Route::get('/profile', 'ProfileController@index')
->name('profile.index');
Route::post('/profile/two-factor/enable', 'ProfileController@enableTwoFactor')
->name('profile.enableTwoFactor');
Route::post('/profile/two-factor/disable', 'ProfileController@disableTwoFactor')
->name('profile.disableTwoFactor');
Route::get('/profile/two-factor/verification', 'ProfileController@getVerifyTwoFactor')
->name('profile.getVerifyTwoFactor');
Route::post('/profile/two-factor/verification', 'ProfileController@postVerifyTwoFactor')
->name('profile.postVerifyTwoFactor');
});
이제 프로필에 대한 탐색을 설정한 다음 탐색해 보겠습니다
resources/views/layouts/partials/navbar.blade.php
. 아래 코드를 참조하십시오.<header class="p-3 bg-dark text-white">
<div class="container">
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
<svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap"><use xlink:href="#bootstrap"/></svg>
</a>
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
<li><a href="#" class="nav-link px-2 text-secondary">Home</a></li>
<li><a href="#" class="nav-link px-2 text-white">Features</a></li>
<li><a href="#" class="nav-link px-2 text-white">Pricing</a></li>
<li><a href="#" class="nav-link px-2 text-white">FAQs</a></li>
<li><a href="#" class="nav-link px-2 text-white">About</a></li>
</ul>
<form class="col-12 col-lg-auto mb-3 mb-lg-0 me-lg-3">
<input type="search" class="form-control form-control-dark" placeholder="Search..." aria-label="Search">
</form>
@auth
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton2" data-bs-toggle="dropdown" aria-expanded="false">
{{auth()->user()->name}}
</button>
<ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="dropdownMenuButton2">
<li><a class="dropdown-item active" href="{{ route('profile.index') }}">Profile</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="{{ route('logout.perform') }}">Logout</a></li>
</ul>
</div>
@endauth
@guest
<div class="text-end">
<a href="{{ route('login.perform') }}" class="btn btn-outline-light me-2">Login</a>
<a href="{{ route('register.perform') }}" class="btn btn-warning">Sign-up</a>
</div>
@endguest
</div>
</div>
</header>
7단계: 인증에서 Authy Two Factor 구현
이제 인증에 Authy Two Factor를 구현해 보겠습니다. L
oginController.php
내부의 인증 코드를 수정해야 합니다. 다음은 수정된 코드 내부authenticated()
메서드입니다.<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\TwoFactor\Authy;
use App\Http\Requests\LoginRequest;
use Illuminate\Support\Facades\Auth;
use App\Services\Login\RememberMeExpiration;
class LoginController extends Controller
{
use RememberMeExpiration;
protected $authy;
public function __construct(Authy $authy)
{
$this->authy = $authy;
}
/**
* Display login page.
*
* @return Renderable
*/
public function show()
{
return view('auth.login');
}
/**
* Handle account login request
*
* @param LoginRequest $request
*
* @return \Illuminate\Http\Response
*/
public function login(LoginRequest $request)
{
$credentials = $request->getCredentials();
if(!Auth::validate($credentials)):
return redirect()->to('login')
->withErrors(trans('auth.failed'));
endif;
$user = Auth::getProvider()->retrieveByCredentials($credentials);
Auth::login($user, $request->get('remember'));
if($request->get('remember')):
$this->setRememberMeExpiration($user);
endif;
return $this->authenticated($request, $user);
}
/**
* Handle response after user authenticated
*
* @param Request $request
* @param Auth $user
*
* @return \Illuminate\Http\Response
*/
protected function authenticated(Request $request, $user)
{
if(!$user->isTwoFactorEnabled()){
return redirect()->intended();
}
$status = $this->authy->verifyUserStatus($user->authy_id);
if($status->ok() && $status->bodyvar('status')->registered) {
Auth::logout();
$request->session()->put('auth.2fa.id', $user->id);
$sms = $this->authy->sendToken($user->authy_id);
if($sms->ok()){
return redirect('/token');
}
} else {
Auth::logout();
return redirect('login')->with('message', __('Could not confirm Authy status!'));
}
}
}
이제 추가 계층 인증을 위해 TwoFactorController를 생성해 보겠습니다. 다음 명령을 실행하여 생성합니다.
php artisan make:controller TwoFactorController
다음은 TwoFactorController의 전체 소스 코드입니다.
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use App\Services\TwoFactor\Authy;
use Illuminate\Support\Facades\Auth;
use App\Http\Requests\TwoFactorVerifyRequest;
class TwoFactorController extends Controller
{
public function __construct(User $users, Authy $authy)
{
$this->users = $users;
$this->authy = $authy;
}
/**
* Display login page.
*
* @return Renderable
*/
public function show()
{
return view('auth.token');
}
public function perform(TwoFactorVerifyRequest $request)
{
$user = $this->users->find(session('auth.2fa.id'));
if(!$user){
return redirect('login');
}
$verfiy = $this->authy->verifyToken($user->authy_id, $request->get('authy_token'));
if($verfiy->ok()){
Auth::login($user);
return redirect('/');
} else {
return redirect('token')->with('authy_error', __('The token you entered is incorrect'));
}
}
}
Two Factor에 대한 유효성 검사 요청을 생성해 보겠습니다. 다음 명령을 실행하십시오.
php artisan make:request TwoFactorVerifyRequest
그런 다음 다음 코드를 추가합니다.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class TwoFactorVerifyRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'authy_token' => ['required', 'digits_between:6,10']
];
}
}
그런 다음 Authy Two Factor를 확인하기 위한 보기를 만들어 보겠습니다.
resources/views/auth
폴더 안에 token.blade.php
파일을 만듭니다. 그런 다음 다음 코드를 추가합니다.@extends('layouts.auth-master')
@section('content')
<form method="post" action="{{ route('token.perform') }}">
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<img class="mb-4" src="{!! url('images/bootstrap-logo.svg') !!}" alt="" width="72" height="57">
<h1 class="h3 mb-3 fw-normal">Two Factor Authentication</h1>
@if(Session::get('authy_error', false))
<div class="alert alert-warning" role="alert">
<i class="fa fa-check"></i>
{{ Session::get('authy_error'); }}
</div>
@endif
<div class="form-group form-floating mb-3">
<input type="text" class="form-control" name="authy_token" value="{{ old('authy_token') }}" placeholder="Authy Token" required="required" autofocus>
<label for="floatingName">Authy Token</label>
@if ($errors->has('authy_token'))
<span class="text-danger text-left">{{ $errors->first('authy_token') }}</span>
@endif
</div>
<button class="w-100 btn btn-lg btn-primary" type="submit">Verify</button>
@include('auth.partials.copy')
</form>
@endsection
그런 다음 이중 요소 경로를 설정해 보겠습니다. 아래를 참조하십시오.
/**
* Two Factor Routes
*/
Route::get('/token', 'TwoFactorController@show')->name('token.show');
Route::post('/token', 'TwoFactorController@perform')->name('token.perform');
다음은 경로의 전체 소스 코드입니다.
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::group(['namespace' => 'App\Http\Controllers'], function()
{
/**
* Home Routes
*/
Route::get('/', 'HomeController@index')->name('home.index');
Route::group(['middleware' => ['guest']], function() {
/**
* Register Routes
*/
Route::get('/register', 'RegisterController@show')->name('register.show');
Route::post('/register', 'RegisterController@register')->name('register.perform');
/**
* Login Routes
*/
Route::get('/login', 'LoginController@show')->name('login.show');
Route::post('/login', 'LoginController@login')->name('login.perform');
/**
* Two Factor Routes
*/
Route::get('/token', 'TwoFactorController@show')->name('token.show');
Route::post('/token', 'TwoFactorController@perform')->name('token.perform');
});
Route::group(['middleware' => ['auth']], function() {
/**
* Profile Routes
*/
Route::get('/profile', 'ProfileController@index')
->name('profile.index');
Route::post('/profile/two-factor/enable', 'ProfileController@enableTwoFactor')
->name('profile.enableTwoFactor');
Route::post('/profile/two-factor/disable', 'ProfileController@disableTwoFactor')
->name('profile.disableTwoFactor');
Route::get('/profile/two-factor/verification', 'ProfileController@getVerifyTwoFactor')
->name('profile.getVerifyTwoFactor');
Route::post('/profile/two-factor/verification', 'ProfileController@postVerifyTwoFactor')
->name('profile.postVerifyTwoFactor');
/**
* Logout Routes
*/
Route::get('/logout', 'LogoutController@perform')->name('logout.perform');
});
});
Laravel 9 Two Factor Authentication을 읽어주셔서 감사합니다. 이 튜토리얼이 도움이 되었으면 합니다. 이 코드를 다운로드하려면 여기https://codeanddeploy.com/blog/laravel/laravel-9-2fa-two-factor-authentication-with-authy를 방문하십시오.
행복한 코딩 :)
Reference
이 문제에 관하여(Laravel 9 2FA - Authy를 사용한 이중 인증), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/codeanddeploy/laravel-9-2fa-two-factor-authentication-with-authy-p07텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)