LoginSignup
6
4

More than 5 years have passed since last update.

【laravel5.7】 MultiAuthにEmailVerificationを対応させる

Last updated at Posted at 2019-02-28

MultiAuthにEmailVerificationを対応させる実装メモ。
【laravel5.7】 MultiAuthログインの続きとして書きます。

MultiAuthなしの実装メモは別記事で書いているので、参考になれば、、、
【laravel5.7】 Email Verificationの使い方

やりたいこと

MultiAuth(Admin/User)のUserのみにEmail Verificationを対応させたい。

環境

MacOS 10.14.3
VisualStudio
laravel 5.7

Email Verificationを使えるようにする

MustVerifyEmailの追加

app/User.php
<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

+class User extends Authenticatable implements MustVerifyEmail
{

ルーティング設定

routes/web.php
<?php

/*
|--------------------------------------------------------------------------
| 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!
|
*/

use Illuminate\Http\Request;

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
// 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');
});

// Admin
以下省略

単体ログインのEmailVerificationのAuth:routes(['verify'=>true]);
MultiAuthでは上の(//emailverify以下の部分)のように一つずつ書いていきます。

VerificationController.php

app/Http/Controllers/User/Auth/VerificationController.php
<?php

+namespace App\Http\Controllers\User\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\VerifiesEmails;
+use Illuminate\Http\Request;


class VerificationController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Email Verification Controller
    |--------------------------------------------------------------------------
    |
    | This controller is responsible for handling email verification for any
    | user that recently registered with the application. Emails may also
    | be re-sent if the user didn't receive the original email message.
    |
    */

    use VerifiesEmails;

    /**
     * Where to redirect users after verification.
     *
     * @var string
     */
+    protected $redirectTo = '/user/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
+        $this->middleware('auth:user');
        $this->middleware('signed')->only('verify');
        $this->middleware('throttle:6,1')->only('verify', 'resend');
    }

+    public function show(Request $request)
+    {
+        return $request->user()->hasVerifiedEmail()
+                        ? redirect($this->redirectPath())
+                        : view('user.auth.verify');
+    }
}

HomeController.php

app/Http/Controllers/User/HomeController.php
    public function __construct()
    {
        $this->middleware('auth:user');
+       $this->middleware('allVerified');
    }

Middleware

AllEnsureEmailIsVerified.phpを作成します

terminal
php artisan make:middleware AllEnsureEmailIsVerified
app/Http/Middleware/AllEnsureEmailIsVerified.php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Support\Facades\Auth;

class AllEnsureEmailIsVerified
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $guards = array_keys(config('auth.guards'));

        foreach($guards as $guard) {
            if($guard == 'user') {
                if (Auth::guard($guard)->check()) {
                    if (! Auth::guard($guard)->user() ||
                        (Auth::guard($guard)->user() instanceof MustVerifyEmail &&
                        ! Auth::guard($guard)->user()->hasVerifiedEmail())) {
                        // dd('ddd');
                        return $request->expectsJson()
                                ? abort(403, 'Your email address is not verified.')
                                : Redirect::route('user.verification.notice');
                    }  
                }
            }
        }
        return $next($request);
    }
}

Kernel.php

app/Http/Kernel.php
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
+       'allVerified' => \App\Http\Middleware\AllEnsureEmailIsVerified::class,
    ];

verify.blade.php

views/user/auth/verify.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">{{ __('メールアドレスの認証') }}</div>

                <div class="card-body">
                    @if (session('resent'))
                        <div class="alert alert-success" role="alert">
                            {{ __('認証メールを再送信しました。') }}
                        </div>
                    @endif

                    {{ __('メールアドレスの認証をしてください。') }}
+                    {{ __('もしメールを受け取ってないなら、<a href="{{ route('user.verification.resend') }}">ここをクリックしてください</a>。') }}
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

メール内容をカスタマイズ

Notificationsの作成

terminal
php artisan make:notification UserVerifyEmailNotification
app/Notifications/UserVerifyEmailNotification.php
<?php

namespace App\Notifications;

use Illuminate\Auth\Notifications\VerifyEmail as VerifyEmailNotification;
use Illuminate\Notifications\Messages\MailMessage;

use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Lang;

class UserVerifyEmailNotification extends VerifyEmailNotification
{
    public function toMail($notifiable)
    {
        if (static::$toMailCallback) {
            return call_user_func(static::$toMailCallback, $notifiable);
        }

        return (new MailMessage)
            ->subject(Lang::getFromJson('USERメール確認'))
            ->line(Lang::getFromJson('クリックして認証してください.'))
            ->action(
                Lang::getFromJson('メール認証'),
                $this->verificationUrl($notifiable)
            )
            ->line(Lang::getFromJson('もしこのメールに覚えが無い場合は破棄してください。'));
    }


    protected function verificationUrl($notifiable)
    {
        return URL::temporarySignedRoute(
            'user.verification.verify', Carbon::now()->addMinutes(60), ['id' => $notifiable->getKey()]
        );
    }
}

User.php

UserVerifyEmailNotificationがメールで送信されるように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\UserVerifyEmailNotification;

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 sendEmailVerificationNotification()
+    {
+        $this->notify(new UserVerifyEmailNotification);
+    }
}

動作確認

User
http://127.0.0.1:8000/user/register から新しくアカウントを登録します。

web
スクリーンショット 2019-03-01 11.27.52.png

登録したメールアドレス
スクリーンショット 2019-02-28 11.48.51.png

メール認証ボタンクリックすると、
68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3235323636372f37653335643530392d353037382d663966382d653163332d6335396463303931653936382e706e67.png

こうなれば成功です。
まだ英語の部分があるので、その辺の設定は後々設定しようと思います。

Adminでも実装したい場合はこれと同様に編集すればOK。
とりあえず以上です。

6
4
1

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
6
4