WEBOPIXEL

Laravel 5.7 の Email Verification(メール認証)を Multi Auth で使用する方法

Posted: 2018.12.21 / Category: PHP / Tag: 

Laravel5.7で新しくEmail Verification(メール認証)という機能が追加されました。
ルートのネームスペースをカスタマイズしたMulti Auth(マルチ認証)環境で動かしてみたので備忘録的に。

Sponsored Link

make:authで認証用ファイルを生成して、マルチ認証でディレクトリを分けた為に、コントローラーをapp/Http/Controllers/Front/Authに、ビューディレクトリをresources/views/front/authディレクトリに移動させた構造で進めます。

$ php artisan make:auth

ルーティング設定

マルチ認証だとルーティングを切り分けたりするかと思います。
今回はnamespaceFrontにして、コントローラーはFrontディレクトリに入れるようにして、asにもfront.を設定しまてます。
また、Auth::routesの引数にverifyを入れることでメール認証用のルーティングが設定されます。

routes/web.php

Route::namespace('Front')->as('front.')->group(function() {
	Auth::routes(['verify' => true]);
	// ...
});

コントーローラーの設定

VerificationControllerにはVerifiesEmailsトレイトが使用されてますが、ここにリダイレクト先やビューのパスが記述されてますのでshowverifyresendをオーバーライドして変更します。

routes/web.php

namespace App\Http\Controllers\Front\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\VerifiesEmails;
use Illuminate\Http\Request;
use Illuminate\Auth\Events\Verified;
use Illuminate\Auth\Access\AuthorizationException;

class VerificationController extends Controller
{
	use VerifiesEmails;

	protected $redirectTo = '/register/comp';

	public function __construct()
	{
		$this->middleware('auth');
		$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('front.auth.verify');
	}

	public function verify(Request $request)
	{
		if ($request->route('id') != $request->user()->getKey()) {
			throw new AuthorizationException;
		}
		
		if ($request->user()->markEmailAsVerified()) {
			event(new Verified($request->user()));
		}
		
		return redirect($this->redirectPath())->with('front.verified', true);
	}

	public function resend(Request $request)
	{
		if ($request->user()->hasVerifiedEmail()) {
			return redirect($this->redirectPath());
		}
		
		$request->user()->sendEmailVerificationNotification();
		
		return back()->with('front.resent', true);
	}
}

登録後に表示されるビューを作成します。

resources/views/front/auth/verify.blade.php

@if (session('resent'))
	<div class="alert is-success">
		新しい本登録メールが送信されました。
	</div>
@endif
<p>
	ご入力頂いたメールアドレスに本登録メールをお送りしました。<br>
	記載されたURLをクリックして登録を完了してください。
</p>
<p>メールが届いていない場合下記ボタンをクリックしてください。</p>
<a href="{{ route('front.verification.resend') }}" class="btn is-primary">確認メールを再発行</a>

メール認証確認用のミドルウェア

EnsureEmailIsVerifiedはメール認証していない場合にverification.noticeルート (VerificationController/show)にリダイレクトさせるミドルウェアです。
ここのルートもverification.noticeにしたいので、app/Http/Middlewareに下記を作成します。
元ファイルはvendor/laravel/framework/src/Illuminate/Auth/Middleware/EnsureEmailIsVerified.phpです。

app/Http/Middleware/EnsureEmailIsVerified.php

namespace App\Http\Middleware;

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

class EnsureEmailIsVerified
{
	public function handle($request, Closure $next)
	{
		if (! $request->user() ||
			($request->user() instanceof MustVerifyEmail &&
				! $request->user()->hasVerifiedEmail())) {
			return $request->expectsJson()
				? abort(403, 'Your email address is not verified.')
				: Redirect::route('front.verification.notice');
		}
		
		return $next($request);
	}
}

Kernel.phprouteMiddlewareverifiedを作成したEnsureEmailIsVerifiedに変更します。

app/Http/Kernel.php

protected $routeMiddleware = [
			// ...
	'verified' => \App\Http\Middleware\EnsureEmailIsVerified::class,
];

ルーターでメール認証が必要なぺージ設定します。
基本的にはauthに置き換えて使用することになるかと思います。

Route::middleware('verified')->group(function() {
	// ...
});

通知メールの設定

通知メール送信時、認証用URLを送信しますが、このURLのルートネームも変更します。

新たにVerifyEmailファイルを作成します。

$ php artisan make:notification VerifyEmail

作成したファイルを下記のようにします。

app/Notifications/VerifyEmail.php

namespace App\Notifications;

use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\URL;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;

class VerifyEmail extends Notification
{
	public static $toMailCallback;

	public function via($notifiable)
	{
		return ['mail'];
	}

	public function toMail($notifiable)
	{
		if (static::$toMailCallback) {
			return call_user_func(static::$toMailCallback, $notifiable);
		}
		
		return (new MailMessage)->view(
			'emails.auth.register', ['url' => $this->verificationUrl($notifiable)]
		)->subject('本登録確認メール');
	}

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

	public static function toMailUsing($callback)
	{
		static::$toMailCallback = $callback;
	}
}

verificationUrlメソッドのルートネームをfront.verification.verifyにします。
これだけでも動きますが、toMailでメールテンプレートも変更しました。

メールはとりあえず下記のようにしました。

resources/views/emails/auth/register.blade.php

アカウント仮登録が完了しました。<br>
以下のURLにアクセスして、本登録を完了させてください。<br>
{{ $url }}

これでユーザーを新規登録したときに確認メールが送られるようになりましたね。