Laravelで簡単に実装!メール認証機能のステップバイステップガイド

この記事では、Webサイトを安全に保つための大切な一歩、Laravelでのメール認証機能の作成方法を初心者の方でも分かりやすく説明します。

Laravelを使えば、難しいコードを一から書くことなく、数ステップで信頼性の高い認証システムを作ることができます。

このガイドでは執筆時(2023年12月)の最新であるLaravel 10系での手順を一つ一つ丁寧に解説していきますので、安心して始めることができます。

なお、Laravelスターターキットである

  • Laravel Breeze
  • Laravel Jetstream

を使用することでこれから紹介する手順のほとんどはスキップする事ができます。パッケージに頼らず、実装方法を1つ1つ確認していきたい人向けの内容になっております。

ユーザーモデルの設定

Laravelでメール認証機能を利用するための最初のステップとして、ユーザーモデルを適切に準備する方法を紹介します。

具体的には、App\Models\User モデルに 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.php ファイルを調べるとわかるように、Laravel には、Illuminate\Auth\Events\Registered イベントにアタッチされた SendEmailVerificationNotification リスナーがすでに含まれています。

<?php

namespace App\Providers;

use App\Listeners\LogVerifiedUser;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Events\Verified;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        Registered::class => [
            SendEmailVerificationNotification::class,
        ],
        Verified::class => [
            LogVerifiedUser::class,
        ],
    ];

    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

このイベント リスナーは、電子メール検証リンクをユーザーに送信します。

    public function handle(Registered $event)
    {
        if ($event->user instanceof MustVerifyEmail && ! $event->user->hasVerifiedEmail()) {
            $event->user->sendEmailVerificationNotification();
        }
    }
    /**
     * Send the email verification notification.
     *
     * @return void
     */
    public function sendEmailVerificationNotification()
    {
        $this->notify(new VerifyEmail);
    }

データベースに必要なカラムの追加

次に、users テーブルにはメールアドレスが検証された日時を保存する email_verified_at カラムが含まれている必要があります。

デフォルトのLaravel フレームワークに含まれる users テーブル設定には、このカラムがすでに含まれています。したがって必要なのはデータベースのマイグレーションを実行することだけです。

php artisan migrate

メール認証のルーティング等を3つ追加

今までの実装で新規登録ユーザーに向けてメール送信を行う事ができるようになりました。

ここからはメール認証に必要なルーティング3つを作成します。

  • 登録後に認証メールを送信した事を知らせるページ
  • 認証メールに含まれる検証用のURL
  • 認証メールの再送信の実行リンク

これらが必要になります。

登録後に認証メールを送信した事を知らせるページ

このルーティングはメールアドレスを確認する必要がある事を知らせるページになります。

Route::get('/email/verify', function () {
    return view('auth.verify-email');
})->middleware('auth')->name('verification.notice');

ルーティングの名前には verification.notice をつける必要があります。

認証メールを確認しないと、Laravelに含まれるログイン検証用ミドルウェアはこのルーティングにリダイレクトされます。(後述)

認証メールに含まれる検証用のURL

次に、検証用のURLを定義します。

このルーティングには、verification.verify という名前を付け、認証および署名されたミドルウェアを割り当てる必要があります。

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');

通常の Request インスタンスは使用せずに、 EmailVerificationRequest インスタンスを使用する事で /email/verify/{id}/{hash} パラメータとログイン済みユーザーとの検証をすることができます。

次に、リクエストに対する $request->fulfill(); 処理の実行をすることでログイン済みのユーザーで markEmailAsVerified メソッドの実行を行います。処理内容は以下。

    public function markEmailAsVerified()
    {
        return $this->forceFill([
            'email_verified_at' => $this->freshTimestamp(),
        ])->save();
    }

email_verified_at カラムに時刻を書き込み、認証済みとして保存します。

認証メールの再送信の実行リンク

一度送った認証メールが手違いで削除してしまったり、届いていない場合の再送信を請求するためのルーティングを作成します。

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');

このルーティングは前述の「登録後に認証メールを送信した事を知らせるページ ( verification.notice )」のページからフォームリクエストによる実行ができるようにしておきましょう。

検証されたユーザーのみへのアクセス制限

前述の認証メールによる検証が済んだユーザー(検証済み)のみがアクセスできるルーティング設定はLaravelに組み込まれているミドルウェアを設定することで制限することができます。

Route::get('/profile', function () {
    // Only verified users may access this route...
})->middleware(['auth', 'verified']);

verified ミドルウェアがそれに相当します。この設定は通常、認証を検出する auth ミドルウェアと同時に使用されます。

未検証のユーザーがこのミドルウェアが割り当てられているルートにアクセスしようとすると、自動的に verify.notice という名前の前述の「登録後に認証メールを送信した事を知らせるページ」にリダイレクトされます。

カスタマイズ、通知メールの内容変更

ここまで紹介した内容でほとんどのメール認証の処理を実現することができます。

ですが、送信するメール内容をカスタマイズする方法をLaravelは提供しているため、その方法を紹介します。

カスタマイズ方法は app/Providers/AuthServiceProvider.php ファイルを確認してください。

use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Notifications\Messages\MailMessage;
 
class AuthServiceProvider extends ServiceProvider
{

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        VerifyEmail::toMailUsing(function ($notifiable, $url) {
            return (new MailMessage())
                ->subject(__('Verify Email Address'))
                ->line(__('Click the button below to verify your email address.'))
                ->action(__('Verify Email Address'), $url);
        });
    }
}

まず、 Illuminate\Auth\Notifications\VerifyEmail 通知によって提供される toMailUsing メソッドにクロージャーを渡します。クロージャはUserモデル インスタンスと、署名付き検証用URLを受け取ります。

このクロージャー内で送信メールの内容を指定しているので、自由にカスタマイズする事が可能です。

クロージャーは Illuminate\Notifications\Messages\MailMessage のインスタンスを返す必要があることに注意してください。

最後に

以上、Laravelのメール認証について解説を行いました。

この記事の内容は Laravelの公式ドキュメントをより詳しく、噛み砕いた内容になっています。元の情報を知りたい方は以下のリンクから確認してみてください。

https://laravel.com/docs/10.x/verification

特別な理由が無ければ Laravel スターターキット を使用したメール認証処理を組み込むのが良いとは思います。処理内容もこの記事で紹介した内容を自動で実装してくれるようになります。

この記事の内容が役に立ちましたら幸いです。

投稿者


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA