はじめに
ほとんどのウェブアプリケーションは、ユーザーが忘れたパスワードをリセットする方法を提供します。作成するすべてのアプリケーションに対して手動でこれを再実装することを強制するのではなく、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
ミドルウェアドキュメントを参照してください。
ルーティング
ユーザーがパスワードをリセットできるようにサポートを適切に実装するには、いくつかのルートを定義する必要があります。まず、ユーザーがメールアドレスを介してパスワードリセットリンクをリクエストできるようにするための一対のルートが必要です。次に、ユーザーがメールで送信されたパスワードリセットリンクを訪れ、パスワードリセットフォームを完了した後に実際にパスワードをリセットするための一対のルートが必要です。
パスワードリセットリンクのリクエスト
パスワードリセットリンクリクエストフォーム
まず、パスワードリセットリンクをリクエストするために必要なルートを定義します。始めるために、パスワードリセットリンクリクエストフォームを持つビューを返すルートを定義します:
Route::get('/forgot-password', function () {
return view('auth.forgot-password');
})->middleware('guest')->name('password.request');
このルートによって返されるビューには、ユーザーが特定のメールアドレスのパスワードリセットリンクをリクエストできるようにするemail
フィールドを含むフォームが必要です。
フォーム送信の処理
次に、「パスワードを忘れた」ビューからのフォーム送信リクエストを処理するルートを定義します。このルートは、メールアドレスを検証し、対応するユーザーにパスワードリセットリクエストを送信する責任があります:
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::RESET_LINK_SENT
? back()->with(['status' => __($status)])
: back()->withErrors(['email' => __($status)]);
})->middleware('guest')->name('password.email');
次に進む前に、このルートをもう少し詳しく見てみましょう。まず、リクエストのemail
属性が検証されます。次に、Laravelの組み込み「パスワードブローカー」(Password
ファサードを介して)を使用して、ユーザーにパスワードリセットリンクを送信します。パスワードブローカーは、指定されたフィールド(この場合はメールアドレス)によってユーザーを取得し、Laravelの組み込み通知システムを介してユーザーにパスワードリセットリンクを送信します。
デフォルトでは、Laravelアプリケーションスケルトンには`````lang`````ディレクトリが含まれていません。Laravelの言語ファイルをカスタマイズしたい場合は、`````lang:publish````` Artisanコマンドを介して公開できます。
Laravelが`````Password`````ファサードの`````sendResetLink`````メソッドを呼び出すときに、アプリケーションのデータベースからユーザーレコードを取得する方法を知っているのか不思議に思うかもしれません。Laravelのパスワードブローカーは、認証システムの「ユーザープロバイダー」を利用してデータベースレコードを取得します。パスワードブローカーによって使用されるユーザープロバイダーは、`````passwords`````設定配列内で構成されます。カスタムユーザープロバイダーの作成については、[認証ドキュメント](6a6e031a57c10fb9.md#adding-custom-user-providers)を参照してください。
パスワードリセットを手動で実装する場合、ビューとルートの内容を自分で定義する必要があります。必要なすべての認証および検証ロジックを含むスキャフォールディングが必要な場合は、[Laravelアプリケーションスターターキット](/read/laravel-11-x/4f3d9f3a392315aa.md)をチェックしてください。
<a name="resetting-the-password"></a>
### パスワードのリセット
<a name="the-password-reset-form"></a>
#### パスワードリセットフォーム
次に、ユーザーがメールで送信されたパスワードリセットリンクをクリックし、新しいパスワードを提供した後に実際にパスワードをリセットするために必要なルートを定義します。まず、ユーザーがパスワードリセットリンクをクリックしたときに表示されるリセットパスワードフォームを表示するルートを定義しましょう。このルートは、後でパスワードリセットリクエストを検証するために使用する`````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
フィールドを含むフォームを表示する必要があります。
フォーム送信の処理
もちろん、パスワードリセットフォームの送信を実際に処理するルートを定義する必要があります。このルートは、受信リクエストを検証し、データベース内のユーザーのパスワードを更新する責任があります:
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::PASSWORD_RESET
? redirect()->route('login')->with('status', __($status))
: back()->withErrors(['email' => [__($status)]]);
})->middleware('guest')->name('password.update');
次に進む前に、このルートをもう少し詳しく見てみましょう。まず、リクエストのtoken
、email
、およびpassword
属性が検証されます。次に、Laravelの組み込み「パスワードブローカー」(Password
ファサードを介して)を使用して、パスワードリセットリクエストの資格情報を検証します。
トークン、メールアドレス、およびパスワードがパスワードブローカーに与えられた場合、reset
メソッドに渡されたクロージャが呼び出されます。このクロージャ内では、ユーザーインスタンスとパスワードリセットフォームに提供されたプレーンテキストパスワードを受け取り、データベース内のユーザーのパスワードを更新できます。
reset
メソッドは「ステータス」スラグを返します。このステータスは、リクエストのステータスに関するユーザーフレンドリーなメッセージを表示するために、Laravelのローカリゼーションヘルパーを使用して翻訳できます。パスワードリセットステータスの翻訳は、アプリケーションのlang/{lang}/passwords.php
言語ファイルによって決定されます。ステータススラグの各可能な値のエントリは、passwords
言語ファイル内にあります。lang
ディレクトリがアプリケーションに存在しない場合は、lang:publish
Artisanコマンドを使用して作成できます。
次に進む前に、LaravelがPassword
ファサードのreset
メソッドを呼び出すときに、アプリケーションのデータベースからユーザーレコードを取得する方法を知っているのか不思議に思うかもしれません。Laravelのパスワードブローカーは、認証システムの「ユーザープロバイダー」を利用してデータベースレコードを取得します。パスワードブローカーによって使用されるユーザープロバイダーは、passwords
設定配列内で構成されます。カスタムユーザープロバイダーの作成については、認証ドキュメントを参照してください。
期限切れトークンの削除
期限切れのパスワードリセットトークンは、データベース内に残ります。ただし、auth:clear-resets
Artisanコマンドを使用してこれらのレコードを簡単に削除できます:
php artisan auth:clear-resets
このプロセスを自動化したい場合は、アプリケーションのスケジューラにコマンドを追加することを検討してください:
use Illuminate\Support\Facades\Schedule;
Schedule::command('auth:clear-resets')->everyFifteenMinutes();
カスタマイズ
リセットリンクのカスタマイズ
``````php
use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
ResetPassword::createUrlUsing(function (User $user, string $token) {
return 'https://example.com/reset-password?token='.$token;
});
}
`
リセットメールのカスタマイズ
ユーザーにパスワードリセットリンクを送信するために使用される通知クラスを簡単に変更できます。始めるには、sendPasswordResetNotification
メソッドをApp\Models\User
モデルでオーバーライドします。このメソッド内で、任意の通知クラスを使用して通知を送信できます。パスワードリセット$token
は、メソッドによって受け取る最初の引数です。この$token
を使用して、任意のパスワードリセットURLを構築し、ユーザーに通知を送信できます:
use App\Notifications\ResetPasswordNotification;
/**
* Send a password reset notification to the user.
*
* @param string $token
*/
public function sendPasswordResetNotification($token): void
{
$url = 'https://example.com/reset-password?token='.$token;
$this->notify(new ResetPasswordNotification($url));
}