--- tags: Laravel, multi-auth, forgot-password, password, reset-password, fortify --- # [簡單版] 處理在Muti-Auth下的Fortify忘記密碼及重設密碼作業 ### 新增自訂的忘記密碼頁面及重設密碼呼叫函式 ```php= #/app/Providers/FortifyServiceProvider.php public function boot() { use App\Actions\Fortify\ResetUserPassword; ... #自訂的忘記密碼頁面 Fortify::requestPasswordResetLinkView('auth.forgot-password'); #重設密碼呼叫函式 Fortify::resetUserPasswordsUsing(ResetUserPassword::class); ... } ``` ### 新增 Route 的宣告,覆蓋原先 fortify 的定義 ```php= #/routes/web.php //忘記密碼 Route::post('/forgot-password', ['App\Actions\Fortify\PasswordResetLinkController','store'])->name('password.email'); //重設密碼 Route::post('/reset-password', ['App\Actions\Fortify\NewPasswordController','store'])->name('password.update'); ``` ### 修改 Auth 套件中忘記密碼的 View 內容,將表單送出到我們自訂函式 1. 這邊的 View 是指在第一個步驟中設定 fortify 來讀的頁面 `Fortify::requestPasswordResetLinkView` 2. 原生的 view 內容可由laravel的原生套件產出,請自行參考相關文件,不再贅述 ```php= ... <form method="POST" action="{{ route('password.email') }}"> ... ``` ### 新增忘記密碼呼叫函式 PasswordResetLinkController.php 這邊擷取主要修改的函式說明 ```php= #app/Actions/Fortify/PasswordResetLinkController.php /** * Send a reset link to the given user. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Contracts\Support\Responsable */ public function store(Request $request): Responsable { $request->validate([Fortify::email() => 'required|email']); //判斷使用者或會員是否有該email $user = $this->broker()->getUser($request->only(Fortify::email())); //使用者 $member = $this->broker('members')->getUser($request->only(Fortify::email())); //會員 //若都沒有則回傳錯誤訊息 if (! $user && ! $member) { return app(FailedPasswordResetLinkRequestResponse::class, ['status' => Password::INVALID_USER]); } //根據前面判斷的身分,設定欲使用的broker來呼叫原生的寄送忘記密碼函式 $status = $this->broker($user ? '' : 'members')->sendResetLink( $request->only(Fortify::email()) ); return $status == Password::RESET_LINK_SENT ? app(SuccessfulPasswordResetLinkRequestResponse::class, ['status' => $status]) : app(FailedPasswordResetLinkRequestResponse::class, ['status' => $status]); } ``` ### 新增重設密碼呼叫函式 NewPasswordController.php 這邊擷取主要修改的函式說明 ```php= #app/Actions/Fortify/NewPasswordController.php /** * Reset the user's password. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Contracts\Support\Responsable */ public function store(Request $request): Responsable { $request->validate([ 'token' => 'required', Fortify::email() => 'required|email', 'password' => 'required', ]); //判斷使用者或會員是否有該email $user = $this->broker()->getUser($request->only(Fortify::email())); //使用者 $member = $this->broker('members')->getUser($request->only(Fortify::email())); //會員 //若都沒有則回傳錯誤訊息 if (! $user && ! $member) { return app(FailedPasswordResetResponse::class, ['status' => Password::INVALID_USER]); } //根據前面判斷的身分,設定欲使用的broker來呼叫原生的重設密碼函式 $status = $this->broker($user ? '' : 'members')->reset( $request->only(Fortify::email(), 'password', 'password_confirmation', 'token'), function ($user) use ($request) { app(ResetsUserPasswords::class)->reset($user, $request->all()); app(CompletePasswordReset::class)($this->guard, $user); } ); // If the password was successfully reset, we will redirect the user back to // the application's home authenticated view. If there is an error we can // redirect them back to where they came from with their error message. return $status == Password::PASSWORD_RESET ? app(PasswordResetResponse::class, ['status' => $status]) : app(FailedPasswordResetResponse::class, ['status' => $status]); } ``` ### 自訂重置使用者密碼的方式 這邊主要是用於自訂修改密碼的檢核或是不同身份資料表格中密碼欄位訂定不一樣等狀況。 ```php= #app/Actions/Fortify/ResetUserPassword.php use PasswordValidationRules; /** * Validate and reset the user's forgotten password. * * @param mixed $user * @param array $input * @return void */ public function reset($user, array $input) { Validator::make($input, [ 'password' => $this->passwordRules(), ])->validate(); //判斷使用者或會員 if ($user->getTable() === 'users') { $user->forceFill(['password' => Hash::make($input['password'])])->save(); } else { $user->forceFill(['passwd' => Hash::make($input['password'])])->save(); } } ```