E-Mail 驗證

簡介

許多的 Web App 都需要使用者先驗證電子郵件位址後才能繼續使用。使用 Laravel 時,開發人員不需要在每個新專案上都自行為這個功能重造輪子。Laravel 提供了方便的內建服務,可用來傳送與驗證電子郵件驗證的 Request。

lightbulb

想要快速入門嗎?請在全新的 Laravel 應用程式內安裝一個 Laravel 應用程式入門套件。這些入門套件會幫你搞定整個驗證系統的 Scaffolding,其中也包含了電子郵件驗證的支援。

Model 的準備

在開始之前,請先確定 App\Models\User Model 有實作 Illuminate\Contracts\Auth\MustVerifyEmail Contract:

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Contracts\Auth\MustVerifyEmail;
6use Illuminate\Foundation\Auth\User as Authenticatable;
7use Illuminate\Notifications\Notifiable;
8 
9class User extends Authenticatable implements MustVerifyEmail
10{
11 use Notifiable;
12 
13 // ...
14}
1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Contracts\Auth\MustVerifyEmail;
6use Illuminate\Foundation\Auth\User as Authenticatable;
7use Illuminate\Notifications\Notifiable;
8 
9class User extends Authenticatable implements MustVerifyEmail
10{
11 use Notifiable;
12 
13 // ...
14}

將該介面加至 Model 後,就會自動傳送一封包含電子郵件驗證連結的 E-Mail 給該使用者。若打開專案的 App\Providers\EventServiceProvider,可以看到,Laravel 已經預先包含了一個 SendEmailVerificationNotification Listener,該 Listener 附加在 Illuminate\Auth\Events\Registered 事件上。該 Event Listener 會傳送電子郵件驗證連結給該使用者:

若不使用入門套件,而是手動在專案中實作註冊功能的話,則請確保有在使用者成功註冊後分派 Illuminate\Auth\Events\Registered 事件:

1use Illuminate\Auth\Events\Registered;
2 
3event(new Registered($user));
1use Illuminate\Auth\Events\Registered;
2 
3event(new Registered($user));

資料庫的準備

接著,users 資料表中應包含一個 email_verified_at 欄位來儲存使用者驗證其電子郵件位址的日期時間。預設情況下,Laravel 內建的 users 資料表的 Migration 中已有該欄位。因此,我們需要做的只有執行資料庫 Migration 而已:

1php artisan migrate
1php artisan migrate

路由

若要正確實作 E-Mail 驗證,我們需要定義三個 Route。第一個 Route 用來顯示提示,告訴使用者必須先點擊驗證郵件中的驗證連結。

第二個 Route 則用來處理使用者點擊信件中 E-Mail 驗證連結時所產生的 Request:

第三個 Route 則用來重新傳送驗證連結,以防使用者不小心遺失之前寄出的驗證連結。

E-Mail 驗證提示

剛才提到過,我們需要定義一個 Route,用來回傳一個 View 告知使用者應點擊註冊後 Laravel 寄出之驗證郵件中的驗證連結。若使用者在沒有驗證 E-Mail 位址的情況下存取了專案中的某部分時,會顯示這個 View 給使用者。請記得,若 App\Models\User Model 有實作 MustVerifyEmail 介面,則驗證連結會自動寄給使用者:

1Route::get('/email/verify', function () {
2 return view('auth.verify-email');
3})->middleware('auth')->name('verification.notice');
1Route::get('/email/verify', function () {
2 return view('auth.verify-email');
3})->middleware('auth')->name('verification.notice');

回傳這個 E-Mail 驗證提示的 Route 應命名為 verification.notice。將 Route 命名為這個名稱非常重要,因為 Laravel 中內建的 verified Middleware 會在使用者尚未驗證 E-Mail 位址時自動重新導向至該 Route 上。

lightbulb

手動實作 E-Mail 驗證時,我們需要自行定義驗證提示中的內容。若想要有包含所有必要之身份驗證與 E-Mail 驗證 View 的 Scaffolding,請參考 Laravel 專案入門套件

E-Mail 驗證的處理常式

接著,我們需要定義一個 Route 來處理使用者點擊 E-Mail 中驗證連結時會產生的 Request。該 Route 應命名為 verification.verify,且應指派 authsigned Middleware 給該 Route:

1use Illuminate\Foundation\Auth\EmailVerificationRequest;
2 
3Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
4 $request->fulfill();
5 
6 return redirect('/home');
7})->middleware(['auth', 'signed'])->name('verification.verify');
1use Illuminate\Foundation\Auth\EmailVerificationRequest;
2 
3Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
4 $request->fulfill();
5 
6 return redirect('/home');
7})->middleware(['auth', 'signed'])->name('verification.verify');

在繼續之前,我們先來進一步看看這個 Route。首先,我們可以注意到我們用的是 EmailVerificationRequest Request 型別,而不是 Illuminate\Http\Request 實體。EmailVerificationRequest 是一個 Laravel 中包含的 Form Request。這個 Request 會自動驗證 Request 的 idhash 引數。

接著,可直接呼叫該 Request 上的 fulfill 方法。該方法會呼叫已登入使用者上的 markEmailAsVerified 方法,並分派 Illuminate\Auth\Event\Verified 事件。App\Models\User 上經由 Illuminate\Foundation\Auth\User 基礎類別提供了 markEmailAsVerified 方法。驗證好使用者的 E-Mail 位址後,就可隨意將使用者重新導向至其他頁面。

重新寄送驗證電子郵件

有時候,使用者可能會不小心搞丟或刪除了 E-Mail 位址驗證信件。為了這種狀況,我們可以定義一個 Route 來讓使用者要求重新寄送驗證信件。接著,我們就可以在驗證提示 View 中加上一個按鈕來產生一個 Request 給該 Route:

1use Illuminate\Http\Request;
2 
3Route::post('/email/verification-notification', function (Request $request) {
4 $request->user()->sendEmailVerificationNotification();
5 
6 return back()->with('message', 'Verification link sent!');
7})->middleware(['auth', 'throttle:6,1'])->name('verification.send');
1use Illuminate\Http\Request;
2 
3Route::post('/email/verification-notification', function (Request $request) {
4 $request->user()->sendEmailVerificationNotification();
5 
6 return back()->with('message', 'Verification link sent!');
7})->middleware(['auth', 'throttle:6,1'])->name('verification.send');

受保護的 Route

可以使用 Route Middleware 來只讓已通過 E-Mail 驗證的使用者存取給定的 Route。Laravel 中隨附了一個 verified Middleware 別名,即 Illuminate\Auth\Middleware\EnsureEmailIsVerified 類別的別名。由於該 Middleware 已預先註冊在專案的 HTTP Kernel 中了,因此我們只需要在 Route 定義中附加該 Middleware 即可。一般來說,該 Middelware 已與 auth Middleware 配對:

1Route::get('/profile', function () {
2 // 只有已驗證使用者可存取此 Route...
3})->middleware(['auth', 'verified']);
1Route::get('/profile', function () {
2 // 只有已驗證使用者可存取此 Route...
3})->middleware(['auth', 'verified']);

若有未驗證的使用者嘗試存取有指派該 Middleware 的 Route,則使用者會自動被重新導向至 verification.notice 命名 Route 中。

自定

自定驗證 E-Mail

雖然預設的 E-Mail 驗證通知應該可以滿足大部分專案的需求,但在 Laravel 中我們也能自定要如何建立 E-Mail 驗證信件的訊息。

若要開始自定郵件內容,請先傳入一個閉包給 Illuminate\Auth\Notifications\VerifyEmail 通知中所提供的 toMailUsing 方法。該閉包會收到一個會收到該通知的 Notifiable Model 實體,以及一個該使用者必須開啟才能驗證 E-Mail 之簽署過的 E-Mail 驗證網址。該閉包應回傳 Illuminate\Notifications\Messages\MailMessage 的實體。一般來說,應在專案的 App\Providers\AuthServiceProvider 類別內 boot 方法中呼叫 toMailUsing 方法:

1use Illuminate\Auth\Notifications\VerifyEmail;
2use Illuminate\Notifications\Messages\MailMessage;
3 
4/**
5 * Register any authentication / authorization services.
6 */
7public function boot(): void
8{
9 // ...
10 
11 VerifyEmail::toMailUsing(function (object $notifiable, string $url) {
12 return (new MailMessage)
13 ->subject('Verify Email Address')
14 ->line('Click the button below to verify your email address.')
15 ->action('Verify Email Address', $url);
16 });
17}
1use Illuminate\Auth\Notifications\VerifyEmail;
2use Illuminate\Notifications\Messages\MailMessage;
3 
4/**
5 * Register any authentication / authorization services.
6 */
7public function boot(): void
8{
9 // ...
10 
11 VerifyEmail::toMailUsing(function (object $notifiable, string $url) {
12 return (new MailMessage)
13 ->subject('Verify Email Address')
14 ->line('Click the button below to verify your email address.')
15 ->action('Verify Email Address', $url);
16 });
17}
lightbulb

若想瞭解更多有關郵件通知的資訊,請參考郵件通知的說明文件

事件

使用 Laravel 專案入門套件時,Laravel 會在 E-Mail 驗證過程中分派多個事件。若是在專案中手動處理 E-Mail 驗證,則我們可能需要手動在驗證完成後分派這些事件。我們可以在專案的 EventServiceProvider 中將 Listener 附加到這些事件上:

1use App\Listeners\LogVerifiedUser;
2use Illuminate\Auth\Events\Verified;
3 
4/**
5 * The event listener mappings for the application.
6 *
7 * @var array
8 */
9protected $listen = [
10 Verified::class => [
11 LogVerifiedUser::class,
12 ],
13];
1use App\Listeners\LogVerifiedUser;
2use Illuminate\Auth\Events\Verified;
3 
4/**
5 * The event listener mappings for the application.
6 *
7 * @var array
8 */
9protected $listen = [
10 Verified::class => [
11 LogVerifiedUser::class,
12 ],
13];
翻譯進度
100% 已翻譯
更新時間:
2023年2月11日 上午10:28: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.