はじめに

ほとんどのウェブアプリケーションは、ユーザーが忘れたパスワードをリセットする方法を提供します。作成するすべてのアプリケーションに対して手動でこれを再実装することを強制するのではなく、Laravelはパスワードリセットリンクを送信し、安全にパスワードをリセットするための便利なサービスを提供します。

すぐに始めたいですか?新しいLaravelアプリケーションにLaravel アプリケーションスターターキットをインストールしてください。Laravelのスターターキットは、忘れたパスワードのリセットを含む、認証システム全体のスキャフォールディングを処理します。

モデルの準備

Laravelのパスワードリセット機能を使用する前に、アプリケーションのApp\Models\UserモデルはIlluminate\Notifications\Notifiableトレイトを使用する必要があります。通常、このトレイトは新しいLaravelアプリケーションで作成されるデフォルトのApp\Models\Userモデルに既に含まれています。

次に、App\Models\UserモデルがIlluminate\Contracts\Auth\CanResetPassword契約を実装していることを確認します。フレームワークに含まれるApp\Models\Userモデルはすでにこのインターフェースを実装しており、インターフェースを実装するために必要なメソッドを含むIlluminate\Auth\Passwords\CanResetPasswordトレイトを使用しています。

データベースの準備

アプリケーションのパスワードリセットトークンを保存するためのテーブルを作成する必要があります。通常、これはLaravelのデフォルトの0001_01_01_000000_create_users_table.phpデータベースマイグレーションに含まれています。

信頼できるホストの設定

デフォルトでは、LaravelはHTTPリクエストのHostヘッダーの内容に関係なく、受信したすべてのリクエストに応答します。さらに、Hostヘッダーの値は、ウェブリクエスト中にアプリケーションへの絶対URLを生成する際に使用されます。

通常、NginxやApacheなどのウェブサーバーを設定して、特定のホスト名に一致するリクエストのみをアプリケーションに送信する必要があります。ただし、ウェブサーバーを直接カスタマイズする能力がない場合や、Laravelに特定のホスト名にのみ応答するよう指示する必要がある場合は、アプリケーションのbootstrap/app.phpファイル内でtrustHostsミドルウェアメソッドを使用して行うことができます。これは、アプリケーションがパスワードリセット機能を提供する場合に特に重要です。

このミドルウェアメソッドの詳細については、TrustHostsミドルウェアドキュメントを参照してください。

ルーティング

ユーザーがパスワードをリセットできるようにサポートを適切に実装するには、いくつかのルートを定義する必要があります。まず、ユーザーがメールアドレスを介してパスワードリセットリンクをリクエストできるようにするための一対のルートが必要です。次に、ユーザーがメールで送信されたパスワードリセットリンクを訪れ、パスワードリセットフォームを完了した後に実際にパスワードをリセットするための一対のルートが必要です。

パスワードリセットリンクのリクエスト

パスワードリセットリンクリクエストフォーム

まず、パスワードリセットリンクをリクエストするために必要なルートを定義します。始めるために、パスワードリセットリンクリクエストフォームを持つビューを返すルートを定義します:

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

このルートによって返されるビューには、ユーザーが特定のメールアドレスのパスワードリセットリンクをリクエストできるようにするemailフィールドを含むフォームが必要です。

フォーム送信の処理

次に、「パスワードを忘れた」ビューからのフォーム送信リクエストを処理するルートを定義します。このルートは、メールアドレスを検証し、対応するユーザーにパスワードリセットリクエストを送信する責任があります:

  1. use Illuminate\Http\Request;
  2. use Illuminate\Support\Facades\Password;
  3. Route::post('/forgot-password', function (Request $request) {
  4. $request->validate(['email' => 'required|email']);
  5. $status = Password::sendResetLink(
  6. $request->only('email')
  7. );
  8. return $status === Password::RESET_LINK_SENT
  9. ? back()->with(['status' => __($status)])
  10. : back()->withErrors(['email' => __($status)]);
  11. })->middleware('guest')->name('password.email');

次に進む前に、このルートをもう少し詳しく見てみましょう。まず、リクエストのemail属性が検証されます。次に、Laravelの組み込み「パスワードブローカー」(Passwordファサードを介して)を使用して、ユーザーにパスワードリセットリンクを送信します。パスワードブローカーは、指定されたフィールド(この場合はメールアドレス)によってユーザーを取得し、Laravelの組み込み通知システムを介してユーザーにパスワードリセットリンクを送信します。

  1. デフォルトでは、Laravelアプリケーションスケルトンには`````lang`````ディレクトリが含まれていません。Laravelの言語ファイルをカスタマイズしたい場合は、`````lang:publish````` Artisanコマンドを介して公開できます。
  2. Laravel`````Password`````ファサードの`````sendResetLink`````メソッドを呼び出すときに、アプリケーションのデータベースからユーザーレコードを取得する方法を知っているのか不思議に思うかもしれません。Laravelのパスワードブローカーは、認証システムの「ユーザープロバイダー」を利用してデータベースレコードを取得します。パスワードブローカーによって使用されるユーザープロバイダーは、`````passwords`````設定配列内で構成されます。カスタムユーザープロバイダーの作成については、[認証ドキュメント](6a6e031a57c10fb9.md#adding-custom-user-providers)を参照してください。
  3. パスワードリセットを手動で実装する場合、ビューとルートの内容を自分で定義する必要があります。必要なすべての認証および検証ロジックを含むスキャフォールディングが必要な場合は、[Laravelアプリケーションスターターキット](/read/laravel-11-x/4f3d9f3a392315aa.md)をチェックしてください。
  4. <a name="resetting-the-password"></a>
  5. ### パスワードのリセット
  6. <a name="the-password-reset-form"></a>
  7. #### パスワードリセットフォーム
  8. 次に、ユーザーがメールで送信されたパスワードリセットリンクをクリックし、新しいパスワードを提供した後に実際にパスワードをリセットするために必要なルートを定義します。まず、ユーザーがパスワードリセットリンクをクリックしたときに表示されるリセットパスワードフォームを表示するルートを定義しましょう。このルートは、後でパスワードリセットリクエストを検証するために使用する`````token`````パラメータを受け取ります:
  9. ``````php
  10. Route::get('/reset-password/{token}', function (string $token) {
  11. return view('auth.reset-password', ['token' => $token]);
  12. })->middleware('guest')->name('password.reset');
  13. `

このルートによって返されるビューは、emailフィールド、passwordフィールド、password_confirmationフィールド、およびルートから受け取った秘密の$tokenの値を含む隠しtokenフィールドを含むフォームを表示する必要があります。

フォーム送信の処理

もちろん、パスワードリセットフォームの送信を実際に処理するルートを定義する必要があります。このルートは、受信リクエストを検証し、データベース内のユーザーのパスワードを更新する責任があります:

  1. use App\Models\User;
  2. use Illuminate\Auth\Events\PasswordReset;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Support\Facades\Hash;
  5. use Illuminate\Support\Facades\Password;
  6. use Illuminate\Support\Str;
  7. Route::post('/reset-password', function (Request $request) {
  8. $request->validate([
  9. 'token' => 'required',
  10. 'email' => 'required|email',
  11. 'password' => 'required|min:8|confirmed',
  12. ]);
  13. $status = Password::reset(
  14. $request->only('email', 'password', 'password_confirmation', 'token'),
  15. function (User $user, string $password) {
  16. $user->forceFill([
  17. 'password' => Hash::make($password)
  18. ])->setRememberToken(Str::random(60));
  19. $user->save();
  20. event(new PasswordReset($user));
  21. }
  22. );
  23. return $status === Password::PASSWORD_RESET
  24. ? redirect()->route('login')->with('status', __($status))
  25. : back()->withErrors(['email' => [__($status)]]);
  26. })->middleware('guest')->name('password.update');

次に進む前に、このルートをもう少し詳しく見てみましょう。まず、リクエストのtokenemail、およびpassword属性が検証されます。次に、Laravelの組み込み「パスワードブローカー」(Passwordファサードを介して)を使用して、パスワードリセットリクエストの資格情報を検証します。

トークン、メールアドレス、およびパスワードがパスワードブローカーに与えられた場合、resetメソッドに渡されたクロージャが呼び出されます。このクロージャ内では、ユーザーインスタンスとパスワードリセットフォームに提供されたプレーンテキストパスワードを受け取り、データベース内のユーザーのパスワードを更新できます。

resetメソッドは「ステータス」スラグを返します。このステータスは、リクエストのステータスに関するユーザーフレンドリーなメッセージを表示するために、Laravelのローカリゼーションヘルパーを使用して翻訳できます。パスワードリセットステータスの翻訳は、アプリケーションのlang/{lang}/passwords.php言語ファイルによって決定されます。ステータススラグの各可能な値のエントリは、passwords言語ファイル内にあります。langディレクトリがアプリケーションに存在しない場合は、lang:publish Artisanコマンドを使用して作成できます。

次に進む前に、LaravelがPasswordファサードのresetメソッドを呼び出すときに、アプリケーションのデータベースからユーザーレコードを取得する方法を知っているのか不思議に思うかもしれません。Laravelのパスワードブローカーは、認証システムの「ユーザープロバイダー」を利用してデータベースレコードを取得します。パスワードブローカーによって使用されるユーザープロバイダーは、passwords設定配列内で構成されます。カスタムユーザープロバイダーの作成については、認証ドキュメントを参照してください。

期限切れトークンの削除

期限切れのパスワードリセットトークンは、データベース内に残ります。ただし、auth:clear-resets Artisanコマンドを使用してこれらのレコードを簡単に削除できます:

  1. php artisan auth:clear-resets

このプロセスを自動化したい場合は、アプリケーションのスケジューラにコマンドを追加することを検討してください:

  1. use Illuminate\Support\Facades\Schedule;
  2. Schedule::command('auth:clear-resets')->everyFifteenMinutes();

カスタマイズ

リセットリンクのカスタマイズ

  1. ``````php
  2. use App\Models\User;
  3. use Illuminate\Auth\Notifications\ResetPassword;
  4. /**
  5. * Bootstrap any application services.
  6. */
  7. public function boot(): void
  8. {
  9. ResetPassword::createUrlUsing(function (User $user, string $token) {
  10. return 'https://example.com/reset-password?token='.$token;
  11. });
  12. }
  13. `

リセットメールのカスタマイズ

ユーザーにパスワードリセットリンクを送信するために使用される通知クラスを簡単に変更できます。始めるには、sendPasswordResetNotificationメソッドをApp\Models\Userモデルでオーバーライドします。このメソッド内で、任意の通知クラスを使用して通知を送信できます。パスワードリセット$tokenは、メソッドによって受け取る最初の引数です。この$tokenを使用して、任意のパスワードリセットURLを構築し、ユーザーに通知を送信できます:

  1. use App\Notifications\ResetPasswordNotification;
  2. /**
  3. * Send a password reset notification to the user.
  4. *
  5. * @param string $token
  6. */
  7. public function sendPasswordResetNotification($token): void
  8. {
  9. $url = 'https://example.com/reset-password?token='.$token;
  10. $this->notify(new ResetPasswordNotification($url));
  11. }