メインコンテンツまでスキップ
バージョン: 8.x

Resetting Passwords

Introduction

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

すぐに始めたいですか?新しい Laravel アプリケーションに Laravel application starter kit をインストールします。 Laravel のスターター キットは、忘れたパスワードのリセットを含む、認証システム全体の足場を処理します。

Model Preparation

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 特性を使用してインターフェイスの実装に必要なメソッドを含めています。

Database Preparation

アプリケーションのパスワードリセット トークンを保存するテーブルを作成する必要があります。このテーブルの移行はデフォルトの Laravel アプリケーションに含まれているため、データベースを移行してこのテーブルを作成するだけで済みます。

php artisan migrate

Configuring Trusted Hosts

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

通常、指定されたホスト名に一致するリクエストのみをアプリケーションに送信するように、Nginx や Apache などの Web サーバーを構成する必要があります。ただし、Web サーバーを直接カスタマイズする機能がなく、特定のホスト名にのみ応答するように Laravel に指示する必要がある場合は、アプリケーションの App\Http\Middleware\TrustHosts ミドルウェアを有効にすることでこれを行うことができます。これは、アプリケーションがパスワードリセット機能を提供する場合に特に重要です。

このミドルウェアの詳細については、TrustHosts middleware documentation を参照してください。

Routing

ユーザーがパスワードをリセットできるようにするサポートを適切に実装するには、いくつかのルートを定義する必要があります。まず、ユーザーが電子メール アドレス経由でパスワードリセット リンクをリクエストできるようにするためのルートのペアが必要です。次に、ユーザーが電子メールで送信されたパスワードリセット リンクにアクセスし、パスワードリセット フォームに記入した後で、実際にパスワードをリセットする処理を行うための 1 組のルートが必要です。

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

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 の組み込み notification system を介したパスワードリセットリンクの送信を処理します。

sendResetLink メソッドは、「ステータス」スラッグを返します。このステータスは、リクエストのステータスに関するわかりやすいメッセージをユーザーに表示するために、Laravel の localization ヘルパを使用して変換できます。パスワードリセット ステータスの翻訳は、アプリケーションの resources/lang/{lang}/passwords.php 言語ファイルによって決まります。ステータス スラッグの考えられる各値のエントリは、passwords 言語ファイル内にあります。

Password ファサードの sendResetLink メソッドを呼び出すときに、Laravel がアプリケーションのデータベースからユーザー レコードを取得する方法をどのように認識するのか疑問に思われるかもしれません。 Laravel パスワードブローカーは、認証システムの「ユーザープロバイダ」を利用してデータベースレコードを取得します。パスワード ブローカーによって使用されるユーザー プロバイダは、config/auth.php 構成ファイルの passwords 構成配列内で構成されます。カスタム ユーザー プロバイダの作成の詳細については、authentication documentation を参照してください。

パスワードのリセットを手動で実装する場合は、ビューとルートの内容を自分で定義する必要があります。必要な認証および検証ロジックをすべて含むスキャフォールディングが必要な場合は、Laravel application starter kits を確認してください。

Resetting The Password

The Password Reset Form

次に、ユーザーが電子メールで送信されたパスワードリセット リンクをクリックして新しいパスワードを入力した後、実際にパスワードをリセットするために必要なルートを定義します。まず、ユーザーがパスワードのリセット リンクをクリックしたときに表示されるパスワードのリセット フォームを表示するルートを定義しましょう。このルートは、後でパスワードリセット要求を確認するために使用する token パラメーターを受け取ります。

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

このルートによって返されるビューには、email フィールド、password フィールド、password_confirmation フィールド、および非表示の token フィールドを含むフォームが表示されます。これらのフィールドには、ルートによって受信されたシークレット $token の値が含まれている必要があります。

Handling The Form Submission

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

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

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

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

reset メソッドは、「ステータス」スラッグを返します。このステータスは、リクエストのステータスに関するわかりやすいメッセージをユーザーに表示するために、Laravel の localization ヘルパを使用して変換できます。パスワードリセット ステータスの翻訳は、アプリケーションの resources/lang/{lang}/passwords.php 言語ファイルによって決まります。ステータス スラッグの考えられる各値のエントリは、passwords 言語ファイル内にあります。

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

Deleting Expired Tokens

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

php artisan auth:clear-resets

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

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

Customization

ResetPassword 通知クラスによって提供される createUrlUsing メソッドを使用して、パスワードリセット リンク URL をカスタマイズできます。このメソッドは、通知を受け取るユーザー インスタンスとパスワードリセット リンク トークンを受け取るクロージャを受け入れます。通常、このメソッドは App\Providers\AuthServiceProvider サービスプロバイダの boot メソッドから呼び出す必要があります。

use Illuminate\Auth\Notifications\ResetPassword;

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

ResetPassword::createUrlUsing(function ($user, string $token) {
return 'https://example.com/reset-password?token='.$token;
});
}

Reset Email Customization

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

use App\Notifications\ResetPasswordNotification;

/**
* Send a password reset notification to the user.
*
* @param string $token
* @return void
*/
public function sendPasswordResetNotification($token)
{
$url = 'https://example.com/reset-password?token='.$token;

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