本文へ移動
Laravel Tips

パスワードの再設定

パスワードを忘れた人のための「パスワードの再設定」を、設定・モデルの準備・ルート・期限切れトークンの削除・メールやリンクの変更まで説明します。

多くのアプリには、パスワードを忘れた人が、自分で新しいパスワードを決められる機能があります。メールで再設定のリンクを送り、そのリンクから新しいパスワードを入れてもらう流れです。Laravel には、再設定のリンクを送る機能と、安全にパスワードを変える機能が最初から入っているので、アプリごとに作り直さなくて済みます。

補足

早く始めたいなら、新しい Laravel アプリにスターターキット(最初から画面や機能がそろった雛形)を入れます。忘れたパスワードの再設定を含む、認証の一式が用意されます。

設定#

パスワードの再設定の設定は、config/auth.php にあります。このファイルのオプションを確かめてください。最初は、database のドライバ(保存の方式)を使う設定になっています。

driver のオプションは、再設定のデータの保存先を決めます。Laravel には、次の2つのドライバがあります。

ドライバ 説明
database 再設定のデータを、リレーショナルデータベース(表でデータを持つデータベース)に保存する
cache 再設定のデータを、キャッシュ(よく使うものを手元に置いておくしくみ)の保存先のどれかに保存する

ドライバの準備#

database の場合#

最初の database ドライバを使うなら、再設定のトークン(合言葉のような値)を入れる表が必要です。Laravel の標準の 0001_01_01_000000_create_users_table.php というマイグレーション(表を作る手順書)に、ふつう入っています。

cache の場合#

専用の表が要らない、cache ドライバもあります。データは、ユーザーのメールアドレスの SHA-256 ハッシュ(元に戻せない形に変えた値)をキーにして保存されます。

php
'passwords' => [
    'users' => [
        'driver' => 'cache',
        'provider' => 'users',
        'store' => 'passwords', // 省略できる
        'expire' => 60,
        'throttle' => 60,
    ],
],

artisan cache:clear を実行したときに、再設定のデータまで消えないようにしたいなら、store で、別の保存先を指定できます。値は、config/cache.php で設定した保存先の名前にします。

モデルの準備#

パスワードの再設定の機能を使う前に、App\Models\User が、Illuminate\Notifications\Notifiable のトレイト(クラスに機能をまとめて足すしくみ)を使っていることが必要です。新しい Laravel アプリの標準の App\Models\User には、ふつう入っています。

次に、App\Models\User が、Illuminate\Contracts\Auth\CanResetPassword という約束事(決まった形)を実装していることを確かめます。Laravel に入っている App\Models\User は、すでに実装していて、必要なメソッドを足してくれる Illuminate\Auth\Passwords\CanResetPassword のトレイトも使っています。

信頼するホストの設定#

Laravel は、HTTP リクエストの Host ヘッダー(相手が「どのドメイン宛てか」を示す情報)の中身にかかわらず、届いたすべてのリクエストに答えます。さらに、Web のリクエストの処理中に、アプリの絶対 URL(https:// から始まる URL)を作るときに、この Host の値を使います。

ふつうは、Nginx や Apache などの Web サーバーの設定で、決まったホスト名宛てのリクエストだけをアプリへ渡します。Web サーバーの設定を変えられず、Laravel に、決まったホスト名にだけ答えさせたいときは、bootstrap/app.php の trustHosts というミドルウェアのメソッドを使います。パスワードの再設定の機能があるアプリでは、とくに大切です。

このメソッドについては、リクエストのページを見てください。

ルート#

ユーザーにパスワードを再設定させるには、いくつかのルート(URL と処理を結びつけたもの)が必要です。1組目は、メールアドレスを入れて、再設定のリンクを求めるルートです。2組目は、メールで届いたリンクから再設定のフォームを送ったときに、実際にパスワードを変えるルートです。

再設定のリンクを求める#

リンクを求めるフォーム#

まず、再設定のリンクを求めるフォームの画面を返すルートを作ります。

php
Route::get('/forgot-password', function () {
    return view('auth.forgot-password');
})->middleware('guest')->name('password.request');

このルートが返すビュー(画面の見た目を書いたファイル)には、email の入力欄のあるフォームを置きます。そのメールアドレスに、再設定のリンクを求めるためのフォームです。

フォームの送信を処理する#

次に、「パスワードを忘れた」画面のフォームの送信を受けるルートを作ります。メールアドレスを確かめ、そのユーザーに、再設定の案内を送ります。

php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;

Route::post('/forgot-password', function (Request $request) {
    $request->validate(['email' => 'required|email']);

    $status = Password::sendResetLink(
        $request->only('email')
    );

    return $status === Password::ResetLinkSent
        ? back()->with(['status' => __($status)])
        : back()->withErrors(['email' => __($status)]);
})->middleware('guest')->name('password.email');

このルートを見ます。まず、リクエストの email を確かめます。次に、Laravel の「パスワードブローカー」(Password ファサードから使う、再設定の仕事を引き受けるしくみ)に、再設定のリンクを送らせます。ブローカーが、指定された項目(ここではメールアドレス)でユーザーを探し、Laravel の通知のしくみで、再設定のリンクを送ります。

sendResetLink は、結果を表す「ステータス」の文字を返します。このステータスは、多言語対応のヘルパーで翻訳でき、ユーザーに分かりやすいメッセージを見せられます。翻訳は、lang/{lang}/passwords.php という言語ファイルで決まります。ステータスのとりうる値ごとに、このファイルに1行あります。

補足

Laravel の最初のアプリには、lang フォルダが入っていません。Laravel の言語ファイルを変えたいときは、lang:publish という Artisan コマンド(php artisan で動かす Laravel のコマンド)で公開できます。

sendResetLink を呼んだときに、Laravel が、どうやってユーザーをデータベースから探すのか、不思議に思うかもしれません。パスワードブローカーは、認証の「ユーザープロバイダ」(ユーザーの取り出し方を決めるしくみ)を使って探します。ブローカーが使うプロバイダは、config/auth.php の passwords の設定で決まります。自分のユーザープロバイダを作る方法は、認証のページを見てください。

補足

パスワードの再設定を自分で作るときは、画面とルートの中身を、自分で作る必要があります。必要な認証の処理が全部そろった雛形がほしいなら、スターターキットを見てください。

パスワードを再設定する#

再設定のフォーム#

次に、ユーザーがメールの再設定のリンクを押して、新しいパスワードを入れたときに、実際にパスワードを変えるルートを作ります。まず、リンクを押したときに出す、再設定のフォームを出すルートです。このルートは、あとで再設定のリクエストを確かめるための token のパラメータを受け取ります。

php
Route::get('/reset-password/{token}', function (string $token) {
    return view('auth.reset-password', ['token' => $token]);
})->middleware('guest')->name('password.reset');

このルートが返すビューには、次の入力欄のあるフォームを置きます。

  • email(メールアドレス)
  • password(新しいパスワード)
  • password_confirmation(新しいパスワードの確認)
  • 隠した token(ルートが受け取った、秘密の $token の値を入れる)

フォームの送信を処理する#

次に、再設定のフォームの送信を処理するルートを作ります。届いた内容を確かめ、データベースのユーザーのパスワードを更新します。

php
use App\Models\User;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;

Route::post('/reset-password', function (Request $request) {
    $request->validate([
        'token' => 'required',
        'email' => 'required|email',
        'password' => 'required|min:8|confirmed',
    ]);

    $status = Password::reset(
        $request->only('email', 'password', 'password_confirmation', 'token'),
        function (User $user, string $password) {
            $user->forceFill([
                'password' => Hash::make($password)
            ])->setRememberToken(Str::random(60));

            $user->save();

            event(new PasswordReset($user));
        }
    );

    return $status === Password::PasswordReset
        ? redirect()->route('login')->with('status', __($status))
        : back()->withErrors(['email' => [__($status)]]);
})->middleware('guest')->name('password.update');

このルートを見ます。まず、リクエストの token・email・password を確かめます。次に、パスワードブローカーを使って、再設定のリクエストの情報が正しいかを確かめます。

ブローカーに渡した、トークン・メールアドレス・パスワードが正しければ、reset に渡したクロージャ(名前のない関数)が呼ばれます。クロージャは、ユーザーと、再設定のフォームに入れられた、そのままの文字のパスワードを受け取ります。ここで、データベースのユーザーのパスワードを更新します。

reset も、結果のステータスの文字を返します。このステータスは、多言語対応のヘルパーで翻訳できます。翻訳は、lang/{lang}/passwords.php で決まります。アプリに lang フォルダがなければ、lang:publish で作れます。

ここでも、reset を呼んだときに、Laravel がユーザーを探す方法は、認証の「ユーザープロバイダ」です。ブローカーが使うプロバイダは、config/auth.php の passwords で決まります。

期限切れのトークンを消す#

database ドライバを使っていると、期限が切れた再設定のトークンも、データベースに残ります。auth:clear-resets という Artisan コマンドで、かんたんに消せます。

bash
php artisan auth:clear-resets

自動で消したいなら、アプリのスケジューラ(決まった時刻に仕事を動かすしくみ)にこのコマンドを足します。

php
use Illuminate\Support\Facades\Schedule;

Schedule::command('auth:clear-resets')->everyFifteenMinutes();

変更する#

再設定のリンクを変える#

再設定のリンクの URL は、ResetPassword という通知のクラスの createUrlUsing で変えられます。ユーザーと、再設定のリンクのトークンを受け取るクロージャを渡します。ふつう、アプリの AppServiceProvider の boot の中で呼びます。

php
use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;

/**
 * アプリのサービスを起動する
 */
public function boot(): void
{
    ResetPassword::createUrlUsing(function (User $user, string $token) {
        return 'https://example.com/reset-password?token='.$token;
    });
}

再設定のメールを変える#

再設定のリンクを送る通知のクラスは、簡単に変えられます。App\Models\User の sendPasswordResetNotification を上書きします(自分のクラスで書き直します)。このメソッドの中で、自分で作った通知のクラスを使って、通知を送れます。メソッドの第1引数が、再設定の $token です。このトークンを使って、好きな再設定の URL を作り、ユーザーに通知を送れます。

php
use App\Notifications\ResetPasswordNotification;

/**
 * ユーザーに、パスワードの再設定の通知を送る
 *
 * @param  string  $token
 */
public function sendPasswordResetNotification($token): void
{
    $url = 'https://example.com/reset-password?token='.$token;

    $this->notify(new ResetPasswordNotification($url));
}

関連するページ#

公式ドキュメント(英語)

2026年10月5日時点の内容をもとに、日本語でまとめています。

ページの一覧