MultiAuthにパスワードリセットを追加する実装メモ
【laravel5.7】 MultiAuthログインの続きとして書きます。
やりたいこと
User/Adminそれぞれにパスワードリセットを実装したい
環境
MacOS 10.14.3
VisualStudio
laravel 5.7
Admin側の設定
auth.php
リセット用のtokenを保存するテーブルが必要なので、auth.phpで設定します。
config/auth.php
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
+ 'admins' => [
+ 'provider' => 'admins',
+ 'table' => 'password_resets',
+ 'expire' => 60,
+ ],
],
Controller
ForgotPasswordController.php
app/Http/Controllers/Admin/Auth/ForgetPasswordController.php
<?php
+namespace App\Http\Controllers\Admin\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class ForgotPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset emails and
| includes a trait which assists in sending these notifications from
| your application to your users. Feel free to explore this trait.
|
*/
use SendsPasswordResetEmails;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
+ $this->middleware('guest:admin');
}
+ public function showLinkRequestForm()
+ {
+ return view('admin.auth.passwords.email');
+ }
+ protected function guard()
+ {
+ return \Auth::guard('admin');
+ }
+ public function broker()
+ {
+ return \Password::broker('admins');
+ }
}
ResetPasswordController.php
app/Http/Controllers/Admin/Auth/ResetPasswordController.php
<?php
+namespace App\Http\Controllers\Admin\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
+use Illuminate\Http\Request;
class ResetPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* @var string
*/
+ protected $redirectTo = '/admin/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
+ $this->middleware('guest:admin');
}
+ public function showResetForm(Request $request, $token = null)
+ {
+ return view('admin.auth.passwords.reset')->with(['token' => $token,'email' => $request->email]);
+ }
+ protected function guard()
+ {
+ return \Auth::guard('admin');
+ }
+ public function broker()
+ {
+ return \Password::broker('admins');
+ }
}
Views
email.blade.php
resources/views/admin/auth/passwords/email.blade.php
+@extends('layouts.admin.auth')
@section('auth')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card mx-4">
<div class="card-body p-4">
<h2>{{ __('Reset Password') }}</h2>
<p class="text-muted">リセットURLを送信します。</p>
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
+ <form method="POST" action="{{ route('admin.password.email') }}">
@csrf
<div class="col-auto">
<div class="input-group mb-3">
<div class="input-group-prepend">
<div class="input-group-text">@</div>
</div>
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required>
</div>
@if ($errors->has('email'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('email') }}</strong>
</span>
@endif
<button type="submit" class="btn btn-primary">
{{ __('Send Password Reset Link') }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
reset.blade.php
resources/views/admin/auth/passwords/reset.blade.php
+@extends('layouts.admin.auth')
@section('auth')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card mx-4">
<div class="card-body p-4">
<h2>{{ __('Reset Password') }}</h2>
{{-- <div class="card-body"> --}}
+ <form method="POST" action="{{ route('admin.password.update') }}">
@csrf
<input type="hidden" name="token" value="{{ $token }}">
<div class="col-auto">
<div class="input-group mb-3">
<div class="input-group-prepend">
<div class="input-group-text">Email</div>
</div>
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ $email ?? old('email') }}" required autofocus>
</div>
@if ($errors->has('email'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('email') }}</strong>
</span>
@endif
</div>
<div class="col-auto">
<div class="input-group mb-3">
<div class="input-group-prepend">
<div class="input-group-text"><i class="fas fa-key"></i></div>
</div>
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>
@if ($errors->has('password'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('password') }}</strong>
</span>
@endif
</div>
</div>
<div class="col-auto">
<div class="input-group mb-3">
<div class="input-group-prepend">
<div class="input-group-text"><i class="fas fa-key"></i></div>
</div>
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Reset Password') }}
</button>
</div>
</div>
</form>
{{-- </div> --}}
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
ルーティング
web.php
routes/web.php
// Admin
Route::group(['namespace' => 'Admin','prefix'=>'admin'],function(){
// home
Route::get('home','HomeController@index')->name('admin.home');
// login logout
Route::get('login','Auth\LoginController@showLoginForm')->name('admin.login');
Route::post('login','Auth\LoginController@login')->name('admin.login');
Route::post('logout','Auth\LoginController@logout')->name('admin.logout');
// register
Route::get('register','Auth\RegisterController@showRegisterForm')->name('admin.register');
Route::post('register','Auth\RegisterController@register')->name('admin.register');
+ // password resets
+ Route::post('password/email','Auth\ForgotPasswordController@sendResetLinkEmail')->name('admin.password.email');
+ Route::post('password/reset','Auth\ResetPasswordController@reset')->name('admin.password.request');
+ Route::get('password/reset','Auth\ForgotPasswordController@showLinkRequestForm')->name('admin.password.update');
+ Route::get('password/reset/{token}','Auth\ResetPasswordController@showResetForm')->name('admin.password.reset');
});
送信機能のオーバーライド
AdminPasswordResetNotification.phpを作ります。
terminal
php artisan make:notification AdminPasswordResetNotification
app/Notifications/AdminPasswordResetNotification.php
<?php
namespace App\Notifications;
use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification;
use Illuminate\Notifications\Messages\MailMessage;
class AdminPasswordResetNotification extends ResetPasswordNotification
{
public function toMail($notifiable)
{
return (new MailMessage)
->line('ADMINパスワードリセット用メール.')
->action('Reset Password', url(config('url').route('admin.password.reset', $this->token, false)))
->line('If you did not request a password reset, no further action is required.');
}
}
Admin.phpの変更
AdminPasswordResetNotificationがメールで送信されるようにModelに設定します。
app/Admin.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
+use App\Notifications\AdminPasswordResetNotification;
class Admin extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password','api_token'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
+ public function sendPasswordResetNotification($token)
+ {
+ $this->notify(new AdminPasswordResetNotification($token));
+ }
}
動作確認
こんな感じで動けばOK
User側の設定
Adminとやることは変わりません
Controller
ForgotPasswordController.php
app/Http/Controllers/User/Auth/ForgetPasswordController.php
<?php
+namespace App\Http\Controllers\User\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class ForgotPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset emails and
| includes a trait which assists in sending these notifications from
| your application to your users. Feel free to explore this trait.
|
*/
use SendsPasswordResetEmails;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
+ $this->middleware('guest:user');
}
+ public function showLinkRequestForm()
+ {
+ return view('user.auth.passwords.email');
+ }
+ protected function guard()
+ {
+ return \Auth::guard('user');
+ }
+ public function broker()
+ {
+ return \Password::broker('users');
+ }
}
ResetPasswordController.php
app/Http/Controllers/User/Auth/ResetPasswordController.php
<?php
+namespace App\Http\Controllers\User\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
+use Illuminate\Http\Request;
class ResetPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* @var string
*/
+ protected $redirectTo = '/user/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
+ $this->middleware('guest:user');
}
+ public function showResetForm(Request $request, $token = null)
+ {
+ return view('user.auth.passwords.reset')->with(['token' => $token,'email' => $request->email]);
+ }
+ protected function guard()
+ {
+ return \Auth::guard('user');
+ }
+ public function broker()
+ {
+ return \Password::broker('users');
+ }
}
Views
email.blade.php
resources/views/user/auth/passwords/email.blade.php
+@extends('layouts.user.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Reset Password') }}</div>
<div class="card-body">
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
+ <form method="POST" action="{{ route('user.password.email') }}">
@csrf
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required>
@if ($errors->has('email'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('email') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Send Password Reset Link') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
reset.blade.php
resources/views/user/auth/passwords/reset.blade.php
+@extends('layouts.user.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Reset Password') }}</div>
<div class="card-body">
+ <form method="POST" action="{{ route('user.password.update') }}">
@csrf
<input type="hidden" name="token" value="{{ $token }}">
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ $email ?? old('email') }}" required autofocus>
@if ($errors->has('email'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('email') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>
@if ($errors->has('password'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('password') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group row">
<label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>
<div class="col-md-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Reset Password') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
ルーティング
web.php
routes/web.php
// User
Route::group(['namespace' => 'User','prefix'=>'user'],function(){
Route::get('/',function(){
return redirect()->to('user/home');
})->name('user');
// home
Route::get('home','HomeController@index')->name('user.home');
// login lgoout
Route::get('login','Auth\LoginController@showLoginForm')->name('user.login');
Route::post('login','Auth\LoginController@login')->name('user.login');
Route::post('logout','Auth\LoginController@logout')->name('user.logout');
// register
Route::get('register','Auth\RegisterController@showRegisterForm')->name('user.register');
Route::post('register','Auth\RegisterController@register')->name('user.register');
// emailverify
Route::middleware('throttle:6,1')->get('email/resend','Auth\VerificationController@resend')->name('user.verification.resend');
Route::middleware('throttle:6,1')->get('email/verify','Auth\VerificationController@show')->name('user.verification.notice');
Route::middleware('signed')->get('email/verify/{id}','Auth\VerificationController@verify')->name('user.verification.verify');
+ // password reset
+ Route::post('password/email','Auth\ForgotPasswordController@sendResetLinkEmail')->name('user.password.email');
+ Route::post('password/reset','Auth\ResetPasswordController@reset')->name('user.password.request');
+ Route::get('password/reset','Auth\ForgotPasswordController@showLinkRequestForm')->name('user.password.update');
+ Route::get('password/reset/{token}','Auth\ResetPasswordController@showResetForm')->name('user.password.reset');
});
送信機能のオーバーライド
UserPasswordResetNotification.phpを作ります。
terminal
php artisan make:notification UserPasswordResetNotification
app/Notifications/UserPasswordResetNotification.php
<?php
namespace App\Notifications;
use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification;
use Illuminate\Notifications\Messages\MailMessage;
class UserPasswordResetNotification extends ResetPasswordNotification
{
public function toMail($notifiable)
{
return (new MailMessage)
->line('USERパスワードリセット用メール.')
->action('Reset Password', url(config('url').route('user.password.reset', $this->token, false)))
->line('If you did not request a password reset, no further action is required.');
}
}
User.phpの変更
UserPasswordResetNotificationがメールで送信されるようにModelに設定します。
app/User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
+use App\Notifications\UserPasswordResetNotification;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
+ public function sendPasswordResetNotification($token)
+ {
+ $this->notify(new UserPasswordResetNotification($token));
+ }
}
動作確認
Adminと同じように動けばOKです。
以上です。