3
5

More than 5 years have passed since last update.

【laravel5.7】MultiAuthにパスワードリセットを追加する

Posted at

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));
+    }
}

動作確認

web
スクリーンショット 2019-02-28 12.56.33.png

入力したメールアドレス
スクリーンショット 2019-02-28 12.56.54.png

Reset Passwordボタンをクリック
スクリーンショット 2019-02-28 13.07.58.png

こんな感じで動けば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です。

メール内容
スクリーンショット 2019-02-28 12.57.22.png

以上です。

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5