Laravel Fortify

簡介

Laravel Fortify 是一個可搭配任意前端的 Laravel 登入後端實作。Fortify 會註冊實作了所有 Laravel 登入功能的路由與 Controller,包含登入、註冊、密碼重設、E-Mail 驗證等功能。安裝完 Fortify 後,可以執行 route:list Artisan 指令,來看看 Fortify 註冊了哪些路由。

由於 Fortify 並不提供 UI,因此你需要自行實作使用這些路由的 UI。在本說明文件中,我們會在稍後討論如何向這些路由建立 Request。

lightbulb

請記得,Fortify 的功能是要讓你能在實作 Laravel 的登入功能時能更快上手。你也可以不使用 Foritfy。若你想要的話,也可以參考 登入驗證密碼重設、與 E-Mail 驗證等說明文件來手動使用 Laravel 的登入服務。

Fortify 是什麼?

剛才也提到過,Laravel Fortify 是一個可搭配任意前端的 Laravel 登入後端實作。Fortify 會註冊實作了所有 Laravel 登入功能的路由與 Controller,包含登入、註冊、密碼重設、E-Mail 驗證等功能。

要使用 Laravel 的登入功能,不一定要用 Foritfy。若想要的話,也可以參考 登入驗證密碼重設、與 E-Mail 驗證等說明文件來手動使用 Laravel 的登入服務。

如果你剛開始接觸 Laravel,你可能會想先看看 Laravel Breeze 專案入門套件,再來嘗試使用 Laravel Fortify。Laravel Breeze 提供了可在專案內使用的登入功能 Scaffolding,包含了使用 Tailwind CSS 製作的 UI。與 Fortify 不同的是,Breeze 會直接將其路由與 Controller 安裝到你的專案內。使用 Breeze,你就可以在實際使用 Laravel Fortify 來實作這些登入功能前,先學習並熟悉 Laravel 的登入功能。

Laravel Fortify 基本上就是將 Laravel Breeze 中的路由與 Controller 拆出來以套件的形式提供給你,並且不包含 UI。這樣一來,使用 Fortify,你還是可以快速的 Scaffold 網站登入功能的後端實作,而不需被綁在某個特定的前端工具。

我該使用 Fortify 嗎?

你可能會想知道,什麼時候才適合使用 Laravel Fortify 呢?首先,如果你已經在使用 Laravel 的其中一個專案入門套件,就不需要再安裝 Laravel Fortify 了。因為,所有的 Laravel 專案入門套件都已經提供了完整的登入實作。

如果你沒有使用專案入門套件,而你的專案需要登入功能的話,則有兩個選項。第一個是你可以手動實作專案的登入功能,另一個選項則是使用 Laravel Fortify 來提供這些功能的後端實作。

若選擇使用 Fortify,則你的 UI 會向本文件中詳細說明的 Fortify 登入路由建立 Request,以登入或註冊使用者。

若選擇不使用 Fortify,手動使用 Laravel 的登入服務,則可參考 登入驗證密碼重設、與 E-Mail 驗證等說明文件。

Laravel Fortify 與 Laravel Sanctum

有的開發人員會搞不清楚 Laravel Sanctum 與 Laravel Fortify 間的差異。這是因為,這兩個套件分別解決了兩個不同但又相關的問題,而 Laravel Fortify 與 Laravel Sanctum 間並不互斥,也不是彼此的替代品。

Laravel Sanctum 只關心如何管理 API Token,以及如何以 Session Cookies 或 Token 來登入現有的使用者。Sanctum 不提供任何處理使用者註冊、密碼重設等的路由。

若要嘗試為有提供 API 或 SPA (單一頁面應用程式,Single-Page Application) 等網站自行建立登入功能,那麼你很有可能會同時用到 Laravel Fortify (用於註冊、重設密碼等) 與 Laravel Sanctum (管理 API Token、Session 登入)。

安裝

若要開始使用 Fortify,可使用 Composer 套件管理員來安裝:

1composer require laravel/fortify
1composer require laravel/fortify

接著,使用 vendor:publish 指令來安裝 Fortify 的資源:

1php artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider"
1php artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider"

這個指令會將 Fortify 的 Action(動作) 安裝到 app/Actions 目錄下,如果這個目錄不存在的話,該指令也會一併建立。此外,也會安裝 FortifyServiceProvider、設定檔、以及所需的 Migration 檔案。

接著,請 Migrate 資料庫:

1php artisan migrate
1php artisan migrate

Fortify Service Provider

剛才提到的 vendor:publish 指令也會安裝 App\Providers\FortifyServiceProvider 類別。請確認是否有在 config/app.php 設定檔中的 providers 陣列中註冊這個類別。

Fortify Service Provider 會註冊 Fortify 所安裝的 Action,並告訴 Fortify 要如何使用這些 Action,以讓 Fortify 來執行並完成其所對應的任務。

Fortify 功能

fortify 設定檔中包含了一個 features 設定陣列。這個陣列定義了 Fortify 預設會提供的後端路由與功能。若不與 Laravel Jetstream 搭配使用 Fortify 的話,我們建議你只啟用下列功能,這些是大多數 Laravel 專案中會提供的基本登入功能:

1'features' => [
2 Features::registration(),
3 Features::resetPasswords(),
4 Features::emailVerification(),
5],
1'features' => [
2 Features::registration(),
3 Features::resetPasswords(),
4 Features::emailVerification(),
5],

禁用 View

預設情況下,Fortify 會定義用於回傳 View 的路由,例如登入畫面、或是註冊畫面。不過,若你正在製作以 JavaScript 驅動的 SPA,則不需要註冊這些路由。這時,可在專案的 config/fortify.php 設定檔中將 views 設定值設為 false 來完全禁用這些路由:

1'views' => false,
1'views' => false,

禁用 View 與密碼重設

若你選擇禁用 Fortify 的 View,但又有需要實作網站的密碼重設功能,則還是需要定義一個名稱為 password.reset 的路由,以用於顯示網站的「重設密碼」View。定義這個路由是有必要的,因為 Laravel 的 Illuminate\Auth\Notifications\ResetPassword 通知會使用這個 password.reset 命名路由來產生密碼重設連結。

登入

若要開始製作登入功能,我們需要告訴 Fortify 如何回傳「登入」View。請記得,Fortify 是一個無周邊 (Headless) 的登入函式庫。若你想要現成的完整 Laravel 登入功能前端實作,請使用專案入門套件

對於所有登入功能的 View,都可使用 Laravel\Fortify\Fortify 類別中相應的方法來自定其轉譯邏輯一般來說,你可以在專案的 App\Providers\FortifyServiceProvider 類別中的 boot 方法內呼叫這些方法。Fortify 會處理並定義 /login 路由,來回傳這個 View:

1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::loginView(function () {
11 return view('auth.login');
12 });
13 
14 // ...
15}
1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::loginView(function () {
11 return view('auth.login');
12 });
13 
14 // ...
15}

你的登入樣板應該包含一個表單,用於向 /login 傳送 POST Request。/login Endpoint 預期一組 email / usernamepassword 的字串輸入。 E-Mail 或帳號 (Username) 的欄位名稱應與 config/fortify.php 中的 username 值相同。此外,也可以提供一個 remember 布林值欄位來表示是否要讓使用者使用 Laravel 提供的「記住我」功能。

若登入嘗試成功,Fortify 會將你重新導向到專案 fortify 設定檔中 home 設定選項所指定的 URI。若登入 Request 是 XHR Request,則會回傳 200 HTTP Response。

若 Request 未成功,則使用者會被重新導向回登入畫面,而共用的 $errors Blade 樣板變數 中會包含驗證錯誤訊息。或者,若使用的是 XHR Request,則會使用 422 HTTP Response 來回傳驗證錯誤。

自定使用者登入

Fortify 會自動依據提供的帳號密碼與專案所設定的登入 Guard 來取得並登入使用者。不過,有時候我們也會需要能完全自定如何驗證帳號密碼與如何取得使用者的邏輯。幸好,在 Fortify 中,我們只要使用 Fortify::authenticateUsing 方法就可以輕鬆達成。

該方法接受一個閉包,該閉包會收到連入的 HTTP Request,並且應負責驗證 Reuqest 中包含的帳號密碼,然後回傳相應的使用者實體。若登入無效,或是找不到使用者,則該閉包應回傳 nullfalse。一般來說,該方法應在 FortifyServiceProvider 中呼叫:

1use App\Models\User;
2use Illuminate\Http\Request;
3use Illuminate\Support\Facades\Hash;
4use Laravel\Fortify\Fortify;
5 
6/**
7 * Bootstrap any application services.
8 *
9 * @return void
10 */
11public function boot()
12{
13 Fortify::authenticateUsing(function (Request $request) {
14 $user = User::where('email', $request->email)->first();
15 
16 if ($user &&
17 Hash::check($request->password, $user->password)) {
18 return $user;
19 }
20 });
21 
22 // ...
23}
1use App\Models\User;
2use Illuminate\Http\Request;
3use Illuminate\Support\Facades\Hash;
4use Laravel\Fortify\Fortify;
5 
6/**
7 * Bootstrap any application services.
8 *
9 * @return void
10 */
11public function boot()
12{
13 Fortify::authenticateUsing(function (Request $request) {
14 $user = User::where('email', $request->email)->first();
15 
16 if ($user &&
17 Hash::check($request->password, $user->password)) {
18 return $user;
19 }
20 });
21 
22 // ...
23}

登入 Guard

可以在專案的 fortify 設定檔中自定 Fortify 使用的登入 Guard。不過,請確保將其設定為有實作 Illuminate\Contracts\Auth\StatefulGuard 的 Guard。若嘗試使用 Fortify 來登入 SPA,則應使用 Laravel 的預設 web Guard,並搭配使用 Laravel Sanctum

自定登入 Pipeline

Laravel Fortify 會通過一組由 Invokable 類別組成的 Pipeline(管道)來驗證登入 Request。若有需要,可定義一組自定的類別 Pipeline 來讓登入 Request 通過。每個類別都應有 __invoke 方法,該方法會收到 Illuminate\Http\Request 實體。然後,像 Middleware 一樣,呼叫 $next 變數來將 Request 傳到 Pipeline 中的下一個類別。

若要定義自定 Pipeline,可以使用 Fortify::authenticateThrough 方法。該方法接受一個閉包,用來回傳一組類別陣列,好讓登入 Request 可通過該 Pipeline。一般來說,該方法應在 App\Providers\FortifyServiceProvider 類別的 boot 方法內呼叫。

下方的範例包含了一組預設的 Pipeline 定義,可讓你在自行修改 Pipeline 時作為參考:

1use Laravel\Fortify\Actions\AttemptToAuthenticate;
2use Laravel\Fortify\Actions\EnsureLoginIsNotThrottled;
3use Laravel\Fortify\Actions\PrepareAuthenticatedSession;
4use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
5use Laravel\Fortify\Fortify;
6use Illuminate\Http\Request;
7 
8Fortify::authenticateThrough(function (Request $request) {
9 return array_filter([
10 config('fortify.limiters.login') ? null : EnsureLoginIsNotThrottled::class,
11 Features::enabled(Features::twoFactorAuthentication()) ? RedirectIfTwoFactorAuthenticatable::class : null,
12 AttemptToAuthenticate::class,
13 PrepareAuthenticatedSession::class,
14 ]);
15});
1use Laravel\Fortify\Actions\AttemptToAuthenticate;
2use Laravel\Fortify\Actions\EnsureLoginIsNotThrottled;
3use Laravel\Fortify\Actions\PrepareAuthenticatedSession;
4use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
5use Laravel\Fortify\Fortify;
6use Illuminate\Http\Request;
7 
8Fortify::authenticateThrough(function (Request $request) {
9 return array_filter([
10 config('fortify.limiters.login') ? null : EnsureLoginIsNotThrottled::class,
11 Features::enabled(Features::twoFactorAuthentication()) ? RedirectIfTwoFactorAuthenticatable::class : null,
12 AttemptToAuthenticate::class,
13 PrepareAuthenticatedSession::class,
14 ]);
15});

自定重新導向

若登入嘗試成功,Fortify 會將你重新導向到專案 fortify 設定檔中 home 設定選項所指定的 URI。若登入 Request 是 XHR Request,則會回傳 200 HTTP Response。使用者登出後網站後,會被重新導向到 / URI。

若有需要自定此行為,可將 LoginResponseLogoutResponse Contract 的實作繫結到 Laravel 的 Service Container 中。一般來說,這些繫結應放在專案 App\Providers\FortifyServiceProviderregister 方法內:

1use Laravel\Fortify\Contracts\LogoutResponse;
2 
3/**
4 * Register any application services.
5 *
6 * @return void
7 */
8public function register()
9{
10 $this->app->instance(LogoutResponse::class, new class implements LogoutResponse {
11 public function toResponse($request)
12 {
13 return redirect('/');
14 }
15 });
16}
1use Laravel\Fortify\Contracts\LogoutResponse;
2 
3/**
4 * Register any application services.
5 *
6 * @return void
7 */
8public function register()
9{
10 $this->app->instance(LogoutResponse::class, new class implements LogoutResponse {
11 public function toResponse($request)
12 {
13 return redirect('/');
14 }
15 });
16}

兩階段驗證

當啟用了 Fortify 的兩步驟驗證時,使用者在登入過程中需要輸入一組 6 位數的 Token。這個 Token 是使用 TOTP (基於時間的一次性密碼,Time-based One-Time Password) 來產生的,可使用如 Google Authenticator 之類任何的 TOTP 相容行動驗證應用程式來取得。

在開始前,請先確保專案的 App\Models\User Model 有 use Laravel\Fortify\TwoFactorAuthenticatable Trait:

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Foundation\Auth\User as Authenticatable;
6use Illuminate\Notifications\Notifiable;
7use Laravel\Fortify\TwoFactorAuthenticatable;
8 
9class User extends Authenticatable
10{
11 use Notifiable, TwoFactorAuthenticatable;
12}
1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Foundation\Auth\User as Authenticatable;
6use Illuminate\Notifications\Notifiable;
7use Laravel\Fortify\TwoFactorAuthenticatable;
8 
9class User extends Authenticatable
10{
11 use Notifiable, TwoFactorAuthenticatable;
12}

接著,我們需要在網站中加上一個畫面,讓使用者可管理其兩步驟驗證設定。該畫面應可讓使用者啟用與禁用兩步驟驗證,以及重新產生其兩步驟驗證恢復代碼。

預設情況下,fortify 設定檔中的 features 陣列應有設定讓 Fortify 要求使用者先驗證密碼,才可修改兩步驟驗證設定。因此,你的專案應先實作 Fortify 的密碼確認功能,才能繼續使用此功能。

啟用兩步驟驗證

若要啟用兩步驟驗證,你的網站需要先向 Fortify 所定義的 /user/two-factor-authentication Endpoint 傳送 POST Request。若 Request 成功,則使用者會被重新導向回之前的 URL,並且 status Session 變數會被設為 two-factor-authentication-enabled。我們可以在樣板中檢查這個 status Session 變數,並顯示適當的成功訊息。若 Request 為 XHR Request,則會回傳 200 HTTP Response:

若選擇啟用兩步驟驗證,則使用者必須先提供一個有效的 2FA 代碼來「確認」其 2FA 設定。因此,畫面上的「成功」訊息應提示使用者仍需進一步確認 2FA:

1@if (session('status') == 'two-factor-authentication-enabled')
2 <div class="mb-4 font-medium text-sm">
3 Please finish configuring two factor authentication below.
4 </div>
5@endif
1@if (session('status') == 'two-factor-authentication-enabled')
2 <div class="mb-4 font-medium text-sm">
3 Please finish configuring two factor authentication below.
4 </div>
5@endif

接著,應顯示兩步驟驗證的 QR Code,來供使用者的驗證 App 掃描。若使用 Blade 來轉譯專案的前端,可使用使用者實體上的 twoFactorQrCodeSvg 方法來取得 QR Code 的 SVG:

1$request->user()->twoFactorQrCodeSvg();
1$request->user()->twoFactorQrCodeSvg();

若使用基於 JavaScript 驅動的前端,可以向 /user/two-factor-qr-code Endpoint 建立一個 XHR GET Request,以取得使用者的兩步驟驗證 QR Code。該 Endpoint 會回傳一個包含 svg 索引鍵的 JSON 物件。

確認 2FA

除了顯示使用者的 2FA QR Code 外,也應提供一個文字輸入框來讓使用者提供有效的 2FA 代碼以「確認」其 2FA 設定。此代碼應通過向 Fortify 所定義的 /user/confirmed-two-factor-authentication Endpoint 傳送 POST Request 來提供給 Laravel。

若 Request 成功,則使用者會被重新導向回其之前瀏覽的 URL,而 status Session 變數會被設為 two-factor-authentication-confirmed

1@if (session('status') == 'two-factor-authentication-confirmed')
2 <div class="mb-4 font-medium text-sm">
3 Two factor authentication confirmed and enabled successfully.
4 </div>
5@endif
1@if (session('status') == 'two-factor-authentication-confirmed')
2 <div class="mb-4 font-medium text-sm">
3 Two factor authentication confirmed and enabled successfully.
4 </div>
5@endif

若使用 XHR Request 來向 2FA 確認 Endpoint 傳送 Request,則會回傳 200 HTTP Response。

顯示恢復代碼

應在網站上顯示使用者的兩步驟驗證恢復代碼。這些恢復代碼可讓使用者在無法存取其行動裝置時用來登入。若使用 Blade 來轉譯專案前端,可以使用已登入使用者實體來存取這些恢復代碼:

1(array) $request->user()->recoveryCodes()
1(array) $request->user()->recoveryCodes()

在製作基於 JavaScript 驅動的前端時,可以向 /user/two-factor-recovery-codes Endpoint 傳送 XHR GET Request。該 Endpoint 會回傳一個包含使用者恢復代碼的 JSON 陣列。

若要重新產生使用者的恢復代碼,請向 /user/two-factor-recovery-codes Endpoint 建立 POST Request。

使用兩步驟驗證進行登入

在登入過程,Fortify 會自動將使用者重新導向到兩步驟驗證畫面。不過,若你的網站使用 XHR 的登入 Request,則成功登入時會回傳一個 JSON Response,其中包含一個擁有 two_factor 布林屬性的 JSON 物件。請檢查該值,以判斷是否應將使用者重新導向到網站的兩步驟驗證畫面。

若要開始實作兩步驟驗證功能,我們需要先告訴 Fortify 如何回傳兩步驟驗證畫面。Fortify 中所有的登入驗證 View 轉譯邏輯都可使用 Laravel\Fortify\Fortify 類別上相應的方法來自定。一般來說,應在專案的 App\Providers\FortifyServiceProvider 類別的 boot 方法內呼叫該方法:

1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::twoFactorChallengeView(function () {
11 return view('auth.two-factor-challenge');
12 });
13 
14 // ...
15}
1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::twoFactorChallengeView(function () {
11 return view('auth.two-factor-challenge');
12 });
13 
14 // ...
15}

Fortify 會負責處理 /two-factor-challenge Route 定義,並回傳該 View。two-factor-challenge 樣板應包含一個表單,用於向 /two-factor-challenge Endpoint 傳送 POST Request。/two-factor-challenge 動作預期收到一個 code 欄位,其中包含有效的 TOTP Token,或是一個包含使用者恢復代碼的 recovery_code 欄位。

若登入嘗試成功,Fortify 會將使用者重新導向到專案 fortify 設定檔中 home 設定選項所指定的 URI。若登入 Request 是 XHR Request,則會回傳 204 HTTP Response。

若 Request 未成功,則使用者會被重新導向回兩步驟驗證畫面,而共用的 $errors Blade 樣板變數 中會包含驗證錯誤訊息。或者,若使用的是 XHR Request,則會使用 422 HTTP Response 來回傳驗證錯誤。

禁用兩步驟驗證

若要禁用兩步驟驗證,則你的網站需要向 /user/two-factor-authentication Endpoint 傳送一個 DELETE Request。請記得,需要先確認密碼,才能呼叫 Fortify 的兩步驟驗證 Endpoint。

註冊

若要開始實作網站的登入功能,我們需要告訴 Fortify 如何回傳「註冊」View。請記得,Fortify 是一個無周邊 (Headless) 的登入函式庫。若你想要現成的完整 Laravel 登入功能前端實作,請使用專案入門套件

Fortify 中所有的 View 轉譯邏輯都可使用 Laravel\Fortify\Fortify 類別中相應的方法來客製化。一般來說,應該在專案的 App\Providers\FortifyServiceProvider 類別中的 boot 方法內呼叫這些方法:

1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::registerView(function () {
11 return view('auth.register');
12 });
13 
14 // ...
15}
1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::registerView(function () {
11 return view('auth.register');
12 });
13 
14 // ...
15}

Fortify 會處理好 /register Route 的定義,並回傳這個 View。register 樣板中應包含一個表單,用來向 Fortify 定義的 /register Endpoint 建立 POST Request。

應傳入一組字串的 name、字串的 E-Mail 位址或使用者名稱、passwordpassword_confirmation 欄位給 /register Endpoint。E-Mail 位址或使用者名稱欄位的名稱應符合專案中 fortify 設定檔內定義的 username 設定值一致。

若註冊嘗試成功,Fortify 會將使用者重新導向到專案 fortify 設定檔中 home 設定選項所指定的 URI。若 Request 是 XHR Request,則會回傳 201 HTTP Response。

若 Request 未成功,則使用者會被重新導向回註冊畫面,而共用的 $errors Blade 樣板變數 中會包含驗證錯誤訊息。或者,若使用的是 XHR Request,則會使用 422 HTTP Response 來回傳驗證錯誤。

自定註冊

只要修改安裝 Laravel Fortify 時產生的 App\Actions\Fortify\CreateNewUser 動作,就可自定驗證與建立使用者的流程。

重設密碼

若要開始實作網站的密碼重設功能,我們需要告訴 Fortify 如何回傳「忘記密碼」View。請記得,Fortify 是一個無周邊 (Headless) 的登入函式庫。若你想要現成的完整 Laravel 登入功能前端實作,請使用專案入門套件

Fortify 中所有的 View 轉譯邏輯都可使用 Laravel\Fortify\Fortify 類別中相應的方法來客製化。一般來說,應在 App\Providers\FortifyServiceProvider 類別中的 boot 方法內呼叫這些方法:

1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::requestPasswordResetLinkView(function () {
11 return view('auth.forgot-password');
12 });
13 
14 // ...
15}
1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::requestPasswordResetLinkView(function () {
11 return view('auth.forgot-password');
12 });
13 
14 // ...
15}

Fortify 會處理好用來回傳此 View 的 /forgot-password Endpoint。forgot-password 樣板中應包含一個表單,用來向 /forgot-password Endpoint 建立 POST Request。

應傳入一個字串的 email 欄位給 /forgot-password Endpoint。該欄位與資料庫欄位的名稱應符合專案中 fortify 設定檔內的 email 設定值。

若要求密碼重設連結成功,Fortify 會將使用者重新導向回 /forgot-password Endpoint,並傳送一封包含安全連結的 E-Mail 給該使用者,以供重設密碼。若使用 XHR Request,則會回傳 200 HTTP Response。

請求成功並重新導向回 /forgot-password Endpoint 後,可使用 status Session 變數來顯示密碼重設連結請求嘗試的狀態。這個 Session 變數的值會是專案中 passwords 語系檔內的其中一個值:

1@if (session('status'))
2 <div class="mb-4 font-medium text-sm text-green-600">
3 {{ session('status') }}
4 </div>
5@endif
1@if (session('status'))
2 <div class="mb-4 font-medium text-sm text-green-600">
3 {{ session('status') }}
4 </div>
5@endif

若 Request 未成功,則使用者會被重新導向回密碼重設連結請求畫面,而共用的 $errors Blade 樣板變數 中會包含驗證錯誤訊息。或者,若使用的是 XHR Request,則會使用 422 HTTP Response 來回傳驗證錯誤。

重設密碼

要實作網站密碼重設功能的最後一個步驟,我們需要告訴 Fortify 如何回傳「重設密碼」View。

Fortify 中所有的 View 轉譯邏輯都可使用 Laravel\Fortify\Fortify 類別中相應的方法來客製化。一般來說,應在 App\Providers\FortifyServiceProvider 類別中的 boot 方法內呼叫這些方法:

1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::resetPasswordView(function ($request) {
11 return view('auth.reset-password', ['request' => $request]);
12 });
13 
14 // ...
15}
1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::resetPasswordView(function ($request) {
11 return view('auth.reset-password', ['request' => $request]);
12 });
13 
14 // ...
15}

Fortify 會處理好用來顯示此 View 的 Route。reset-password 樣板中應包含一個表單,用來向 /reset-password Endpoint 建立 POST Request。

應傳入一組字串的 emailpasswordpassword_confirmation、以及一個隱藏的 token 欄位給 /reset-password Endpoint。token欄位應包含request()->route('token')的值。而「電子郵件」欄位與資料庫欄位的名稱應與專案中fortify設定檔的email` 設定值相同。

處理密碼重設的 Response

成功重設密碼後,Fortify 會重新導向回 /login Route,好讓使用者能以新密碼登入。此外,Fortify 也會設定 status Session 變數,讓你能在登入畫面上顯示重設的成功狀態:

1@if (session('status'))
2 <div class="mb-4 font-medium text-sm text-green-600">
3 {{ session('status') }}
4 </div>
5@endif
1@if (session('status'))
2 <div class="mb-4 font-medium text-sm text-green-600">
3 {{ session('status') }}
4 </div>
5@endif

若 Request 為 XHR Request,則會回傳 200 HTTP Response。

若 Request 未成功,則使用者會被重新導向回重設密碼畫面,而共用的 $errors Blade 樣板變數 中會包含驗證錯誤訊息。或者,若使用的是 XHR Request,則會使用 422 HTTP Response 來回傳驗證錯誤。

自定密碼重設

只要修改安裝 Laravel Fortify 時產生的 App\Actions\Fortify\ResetUserPassword 動作,就可自定重設密碼的流程。

E-Mail 驗證

註冊好後,你可能也會想讓使用者在繼續使用網站前先驗證其 E-Mail 位址。若要驗證使用者的 E-Mail 位址,請在 fortify 設定檔中的 features 陣列內啟用 emailVerification 功能。接著,請確保有 App\Models\User 類別有實作 Illuminate\Contracts\Auth\MustVerifyEmail 介面。

完成這兩個步驟後,新註冊的使用者就會收到一封 E-Mail,提醒他們要驗證其 E-Mail 位址。不過,我們還需要告訴 Fortify 如何顯示 E-Mail 驗證畫面,用來告訴使用者要點擊 E-Mail 中的驗證連結。

Fortify 中所有的 View 轉譯邏輯都可使用 Laravel\Fortify\Fortify 類別中相應的方法來客製化。一般來說,應在 App\Providers\FortifyServiceProvider 類別中的 boot 方法內呼叫這些方法:

1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::verifyEmailView(function () {
11 return view('auth.verify-email');
12 });
13 
14 // ...
15}
1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::verifyEmailView(function () {
11 return view('auth.verify-email');
12 });
13 
14 // ...
15}

Fortify 會處理好用來使用者被 Laravel 內建的 verified Middleware 重新導向到 /email/verify Endpoint 時顯示這個 View 的 Route 定義。

verify-email 樣板中應顯示提示訊息,告訴使用者要點擊寄送到其 E-Mail 位址內的 E-Mail 驗證連結。

若有需要,也可以在 verify-email 樣板內加上一個按鈕,用來向 /email/verification-notification Endpoint 傳送 POST Request。當此 Endpoint 收到 Request 後,會寄送一封新的 E-Mail 驗證連結給該使用者,以免使用者不小心刪除或沒收到之前寄送的驗證連結。

若重新寄送驗證連結的 Request 成功,則 Fortify 會將使用者重新導向回 /email/verify Endpoint,並設定 status Session 變數,讓你可以顯示提示訊息告訴使用者此操作已成功執行。若 Request 為 XHR Request,則會回傳 202 HTTP Response:

1@if (session('status') == 'verification-link-sent')
2 <div class="mb-4 font-medium text-sm text-green-600">
3 A new email verification link has been emailed to you!
4 </div>
5@endif
1@if (session('status') == 'verification-link-sent')
2 <div class="mb-4 font-medium text-sm text-green-600">
3 A new email verification link has been emailed to you!
4 </div>
5@endif

保護 Route

若要指定某個 Route 或某一組 Route 需要求使用者先進行 E-Mail 位址驗證,則可在這些 Route 上加入 Laravel 的內建 verified Middleware。此 Middleware 已在 App\Http\Kernel 類別內註冊:

1Route::get('/dashboard', function () {
2 // ...
3})->middleware(['verified']);
1Route::get('/dashboard', function () {
2 // ...
3})->middleware(['verified']);

密碼確認

在製作網站時,有時候會有一些動作是在執行前需要先向使用者要求確認密碼的。一般來說,這些 Route 是由 Laravel 的內建 password.confirm Middleware 所保護的。

若要開始實作網站的密碼確認功能,我們需要告訴 Fortify 如何回傳「確認密碼」View。請記得,Fortify 是一個無周邊 (Headless) 的登入函式庫。若你想要現成的完整 Laravel 登入功能前端實作,請使用專案入門套件

Fortify 中所有的 View 轉譯邏輯都可使用 Laravel\Fortify\Fortify 類別中相應的方法來客製化。一般來說,應在 App\Providers\FortifyServiceProvider 類別中的 boot 方法內呼叫這些方法:

1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::confirmPasswordView(function () {
11 return view('auth.confirm-password');
12 });
13 
14 // ...
15}
1use Laravel\Fortify\Fortify;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Fortify::confirmPasswordView(function () {
11 return view('auth.confirm-password');
12 });
13 
14 // ...
15}

Fortify 會處理好用來回傳此 View 的 /user/confirm-password Endpoint。confirm-password 樣板中應包含一個表單,用來向 /user/confirm-password Endpoint 建立 POST Request。應傳送一個包含使用者目前密碼的 password 欄位給 /user/confirm-password Endpoint。

若送出的密碼符合該使用者目前的密碼,則 Fortify 會將使用者重新導向回該使用者原本嘗試存取的 Route。若 Request 為 XHR Request,則會回傳 201 HTTP Response。

若 Request 未成功,則使用者會被重新導向回確認密碼畫面,而共用的 $errors Blade 樣板變數中會包含驗證錯誤訊息。或者,若使用的是 XHR Request,則會使用 422 HTTP Response 來回傳驗證錯誤。

翻譯進度
100% 已翻譯
更新時間:
2023年2月11日 下午12:59:00 [世界標準時間]
翻譯人員:
  • cornch
幫我們翻譯此頁

留言

尚無留言

“Laravel” is a Trademark of Taylor Otwell.
The source documentation is released under MIT license. See laravel/docs on GitHub for details.
The translated documentations are released under MIT license. See cornch/laravel-docs-l10n on GitHub for details.