#はじめに
多くのウェブアプリケーションでは、ユーザーがアプリケーションを利用する前にメールアドレスの認証が必要です。Laravelは、この機能を毎回手動で実装する代わりに、メール認証リクエストの送信と検証を簡単に行える組み込みサービスを提供しています。
すぐに始めたい場合は、新しいLaravelアプリケーションにLaravelアプリケーションのスターターキットのいずれかをインストールしてください。スターターキットは、メール認証サポートを含む認証システム全体のスキャフォールディングを自動で行います。
#モデルの準備
始める前に、App\Models\UserモデルがIlluminate\Contracts\Auth\MustVerifyEmailインターフェイスを実装していることを確認してください:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
// ...
}
このインターフェイスをモデルに追加すると、新規登録ユーザーには自動的にメール認証リンクが記載されたメールが送信されます。App\Providers\EventServiceProviderを確認すると、LaravelにはすでにIlluminate\Auth\Events\Registeredイベントに紐づくSendEmailVerificationNotification リスナーがあり、このリスナーが認証メールを送信します。
アプリケーションで スターターキット を使用せずに登録を手動で実装している場合は、ユーザーの登録が成功した後に Illuminate\Auth\Events\Registered イベントをディスパッチしていることを確認してください:
use Illuminate\Auth\Events\Registered;
event(new Registered($user));
#データベースの準備
次に、usersテーブルにユーザーのメールアドレスが認証された日時を保存するemail_verified_atカラムが必要です。Laravelのデフォルトのusersテーブルマイグレーションにはすでにこのカラムが含まれているため、マイグレーションを実行するだけで準備完了です。
php artisan migrate
#ルーティング
メール認証を正しく実装するには、3つのルートを定義する必要があります。まず、登録後にLaravelが送信した認証メールのリンクをクリックするようユーザーに通知するためのルートです。
次に、ユーザーが認証メールのリンクをクリックした際のリクエストを処理するルートが必要です。
最後に、ユーザーが最初の認証リンクを紛失した場合に再送信を行うためのルートが必要です。
#メール認証通知
前述の通り、登録後にLaravelから送信されたメール認証リンクをクリックするようユーザーに促すビューを返すルートを定義してください。このビューは、ユーザーがメール認証を完了せずに他の部分にアクセスしようとした際に表示されます。App\Models\UserモデルがMustVerifyEmailインターフェイスを実装していれば、リンクは自動的に送信されます:
Route::get('/email/verify', function () {
return view('auth.verify-email');
})->middleware('auth')->name('verification.notice');
メール確認通知を返すルートは verification.notice という名前にする必要があります。ユーザーがメールアドレスを確認していない場合、verified ミドルウェア Laravelに含まれる が自動的にこのルート名にリダイレクトするため、ルートに正確にこの名前が割り当てられていることが重要です。
メール認証を手動で実装する場合、認証通知ビューの内容は自分で定義する必要があります。必要な認証・認証ビューを含むスキャフォールディングが欲しい場合は、Laravelアプリケーションのスターターキットを参照してください。
#メール認証ハンドラー
次に、ユーザーが認証メールのリンクをクリックした際のリクエストを処理するルートを定義します。このルートはverification.verifyという名前にし、authとsignedミドルウェアを割り当てます:
use Illuminate\Foundation\Auth\EmailVerificationRequest;
Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
$request->fulfill();
return redirect('/home');
})->middleware(['auth', 'signed'])->name('verification.verify');
このルートを詳しく見てみましょう。まず、通常のIlluminate\Http\RequestではなくEmailVerificationRequestを使っていることに注目してください。EmailVerificationRequestはLaravelに含まれるフォームリクエストで、idとhashパラメータの検証を自動で行います。
次に、fulfillメソッドを呼び出します。このメソッドは認証済みユーザーのmarkEmailAsVerifiedメソッドを呼び出し、Illuminate\Auth\Events\Verifiedイベントを発火します。markEmailAsVerifiedはデフォルトのApp\Models\Userモデルが継承するIlluminate\Foundation\Auth\Userクラスで利用可能です。メール認証が完了したら、任意の場所にリダイレクトできます。
#認証メールの再送信
ユーザーが認証メールを紛失または誤って削除することがあります。そのため、認証メールの再送信をリクエストできるルートを定義すると便利です。このルートには、認証通知ビューに簡単なフォーム送信ボタンを設置してリクエストできます:
use Illuminate\Http\Request;
Route::post('/email/verification-notification', function (Request $request) {
$request->user()->sendEmailVerificationNotification();
return back()->with('message', 'Verification link sent!');
})->middleware(['auth', 'throttle:6,1'])->name('verification.send');
#ルートの保護
ルートミドルウェアを使うと、認証済みユーザーのみが特定のルートにアクセスできるようにできます。Laravelにはverifiedというミドルウェアエイリアスがあり、これはIlluminate\Auth\Middleware\EnsureEmailIsVerifiedクラスのエイリアスです。このミドルウェアはアプリケーションのHTTPカーネルに登録済みなので、ルート定義にミドルウェアを割り当てるだけで利用できます。通常はauthミドルウェアと組み合わせて使います:
Route::get('/profile', function () {
// 認証済みユーザーのみがこのルートにアクセスできます...
})->middleware(['auth', 'verified']);
未認証ユーザーがこのミドルウェアが割り当てられたルートにアクセスしようとすると、自動的にverification.noticeという名前付きルートにリダイレクトされます。
#カスタマイズ
#認証メールのカスタマイズ
デフォルトのメール認証通知はほとんどのアプリケーションで十分ですが、Laravelでは認証メールのメッセージ構築方法をカスタマイズできます。
始めるには、Illuminate\Auth\Notifications\VerifyEmail通知のtoMailUsingメソッドにクロージャを渡します。クロージャは通知を受け取るモデルインスタンスと、ユーザーがメール認証に訪れる署名付きURLを受け取ります。クロージャはIlluminate\Notifications\Messages\MailMessageのインスタンスを返す必要があります。通常はアプリケーションのApp\Providers\AuthServiceProviderクラスのbootメソッド内でtoMailUsingを呼び出します:
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Notifications\Messages\MailMessage;
/**
* 認証・認可サービスを登録します。
*/
public function boot(): void
{
// ...
VerifyEmail::toMailUsing(function (object $notifiable, string $url) {
return (new MailMessage)
->subject('Verify Email Address')
->line('Click the button below to verify your email address.')
->action('Verify Email Address', $url);
});
}
メール通知について詳しくは、メール通知のドキュメントを参照してください。
#イベント
Laravelアプリケーションのスターターキットを使うと、メール認証プロセス中にイベントが発火します。手動でメール認証を実装する場合は、認証完了後にこれらのイベントを手動で発火させることもできます。アプリケーションのEventServiceProviderでこれらのイベントにリスナーを紐づけられます:
use App\Listeners\LogVerifiedUser;
use Illuminate\Auth\Events\Verified;
/**
* アプリケーションのイベントリスナーのマッピング。
*
* @var array
*/
protected $listen = [
Verified::class => [
LogVerifiedUser::class,
],
];