Resetting Passwords
Table of Contents
Introduction
ほとんどの web アプリケーションは、 users が忘れた passwords を reset するための方法を提供しています。すべての application でこれを手作業で再実装するのを強制する代わりに、 Laravel は password reset links を送信し、安全に passwords をリセットするための便利な services を提供しています。
NOTE
速く始めたいですか? 新鮮な Laravelapplication に、Laravel のアプリケーション スターターキットをインストールしてください。Laravel のスターターキットは、passwords を忘れて reset する事を含む全体の authentication システムの足場を整えることを担当します。
Model の準備
Laravel の password reset 機能を使用する前に、application のApp\Models\User
model は Illuminate\Notifications\Notifiable
トレイトを使用する必要があります。通常、このトレイトは新しい Laravel application で作成される default の App\Models\User
model にすでに含まれています。
次に、あなたの App\Models\User
model が Illuminate\Contracts\Auth\CanResetPassword
コントラクトを実装していることを確認してください。 フレームワークに含まれる App\Models\User
model はすでにこのインタフェースを宝装しており、Illuminate\Auth\Passwords\CanResetPassword
トレイトを使用してインタフェースを実装するために必要な methods を含んでいます。
Database の準備
あなたのアプリケーションの password reset tokens を保存するためのテーブルを作成する必要があります。通常、これは Laravel の default 0001_01_01_000000_create_users_table.php
database マイグレーションに含まれています。
信頼できる Hosts の設定
default では、Laravel は、Host
header の HTTPrequests の content に関係なく、受信したすべての requests に response します。さらに、Host
header の value は、web request 中にあなたの application への絶対 URL を生成する際に使用されます。
通常、Nginx や Apache のような webserver を、特定のホスト名にマッチする requests のみを application に送信するように設定するべきです。しかし、webserver を直接カスタマイズする能力がなく、特定のホスト名にのみ Laravel が response するよう指示する必要がある場合、アプリケーションのbootstrap/app.php
ファイルでtrustHosts
middlewaremethod を使用して行うことができます。これは、application が password reset 機能を提供している場合に特に重要です。
この middleware method について詳しく知るためには、TrustHosts
middleware ドキュメントをご覧ください。
Routing
users が reset を使って passwords を変更するためのサポートを適切に実装するには、いくつかの routes を定義する必要があります。まず、user が email アドレスを通じて password resetlink を request できるようにする routes を 1 組必要とします。次に、user が mail で送信された password resetlink を訪問し、password reset フォームを完成させると、実際に password を reset するための routes を 1 組必要とします。
Password Reset リンクのリクエスト
Password Reset リンク Request フォーム
まず、 request password reset links が必要な routes を定義します。始めるために、 password reset リンク request フォームを含む view を返す route を定義します:
Route::get('/forgot-password', function () {
return view('auth.forgot-password');
})->middleware('guest')->name('password.request');
この route によって返される view には、email
フィールドを含むフォームがあるべきで、このフォームを使用して user が指定された email アドレスの password reset リンクの request を行うことができます。
フォーム送信の処理
次に、"forgot password"の view からのフォーム送信の request を処理する route を定義します。この route は、 email アドレスの validating と対応する user への password reset request の送信を担当します。
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');
先に進む前に、この route を詳しく見てみましょう。まず、request の email
attribute が検証されます。次に、Laravel の組み込みの"password broker"(Password
facade を介して)を使用して、password resetlink を user に送信します。 password ブローカーは、指定されたフィールド(この場合、email アドレス)によって user を取得し、Laravel の組み込みのnotification systemを介して user に password resetlink を送信することを担当します。
sendResetLink
method は、"status" slug を返します。この status は、Laravel のローカライゼーション helpers を使って、user に対してその request の status に関するユーザーフレンドリーなメッセージを表示するために翻訳することができます。password reset ステータスの翻訳は、あなたの application のlang/{lang}/passwords.php
言語ファイルによって決定されます。status slug の各可能な value に対するエントリは passwords
言語ファイル内に位置しています。
NOTE
By default, the Laravel application skeleton does not include the
lang
directory. If you would like to customize Laravel's language files, you may publish them via thelang:publish
Artisan command.
どうやって Laravel が、Password
facade のsendResetLink
method を呼び出すときに、あなたの application の database から user レコードを取得するのか、疑問に思うかもしれません。Laravel の password ブローカーは、あなたの authentication システムの userprovider を使用して database レコードを取得します。password ブローカーに使用される userprovider は、config/auth.php
設定ファイルのpasswords
設定 array 内で設定されます。customuserprovider の作成方法について詳しくは、authentication ドキュメンテーションを参照してください。
NOTE
手動で password を reset する際、views と routes の内容を自分で定義する必要があります。全ての必要な authentication と検証ロジックを含むスキャフォールディングが欲しい場合は、 Laravel application スターターキットをチェックしてみてください。
Resetting the Password
Password Reset フォーム
次に、 routes を定義して、 user がメールで送られてきた password reset のリンクをクリックし、新しい password を提供した際に、実際に password を reset するために必要な手順を説明します。まず、 user が reset password のリンクをクリックしたときに表示される reset password フォームを表示する、 route を定義しましょう。この route は、後で password reset request を検証するために使用するtoken
パラメータを受け取ります。
Route::get('/reset-password/{token}', function (string $token) {
return view('auth.reset-password', ['token' => $token]);
})->middleware('guest')->name('password.reset');
この route によって返される view は、email
フィールド、password
フィールド、password_confirmation
フィールド、および hidden token
フィールドを含むフォームを表示する必要があります。この token
フィールドには、route から受け取った secret $token
の value を含める必要があります。
フォーム送信の処理
もちろん、実際に password reset のフォーム提出を handle するためには、 route を定義する必要があります。この route は、受信した request を validating し、ユーザーの password を database で更新する役割を果たします。
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');
先に進む前に、この route を詳しく見てみましょう。まず、リクエストの token
、email
、および password
attributes が validate されます。次に、Laravel の組み込みの "password broker" (Password
facade) を使用して、password reset request の資格情報を validate します。
与えられた token 、 email アドレス、そして password が password ブローカーに対して有効であれば、reset
method に渡されたクロージャが呼び出されます。このクロージャの中で、 password reset フォームに提供された平文の password と user インスタンスを受け取り、我々はユーザーの password を database で update することが可能です。
reset
method は"status" slug を返します。この status は、Laravel のlocalization helpers を使用して、user への request の status を user フレンドリーなメッセージで表示するために翻訳できます。 password reset status の翻訳は、あなたの application のlang/{lang}/passwords.php
言語ファイルで決定されます。"status slug"の各可能な value のエントリーは、passwords
言語ファイル内に存在します。もしあなたの application にlang
ディレクトリが含まれていないなら、lang:publish
Artisan command を使用して作成することができます。
次に進む前に、Password
facade の reset
method を呼び出すときに、どうやって Laravel が application の database から user レコードを取得するかを不思議に思うかもしれません。 Laravel password ブローカーは、あなたの authentication システムの "user providers" を利用して database レコードを取得します。 password ブローカーによって利用される user provider は、config/auth.php
設定ファイルの passwords
設定 array の中で設定されています。 custom user providers の作成方法について詳しく学ぶためには、 authentication documentation を参照してください。
Deleting Expired Tokens
期限切れの Password reset tokens は、 database 内に引き続き存在します。しかし、これらのレコードは auth:clear-resets
Artisan command を使用して簡単に delete することができます:
php artisan auth:clear-resets
この process を自動化したい場合は、アプリケーションのschedulerに command を追加することを検討してみてください。
use Illuminate\Support\Facades\Schedule;
Schedule::command('auth:clear-resets')->everyFifteenMinutes();
Customization
Reset リンクのカスタマイズ
ResetPassword
通知 class で提供されるcreateUrlUsing
method を使用して、password resetlink の URL をカスタマイズできます。この method は、notification を受け取っているユーザインスタンスと password resetlink の token を受け取るクロージャを受け入れます。通常は、App\Providers\AppServiceProvider
の service provider のboot
method からこの method を呼び出すべきです。
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;
});
}
Reset Email カスタマイズ
App\Models\User
model 上のsendPasswordResetNotification
メソッドをオーバーライドすることで、password resetlink の送信に使用する通知 class を簡単に変更することができます。この method 内で、自分で作成した通知 classを用いて通知を送信することができます。password reset の$token
は、この method によって最初に受け取る引数です。この$token
を使用して、自分の選択した passwordresetURL を構築し、その通知を user に送信することができます。
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));
}