邮箱验证
介绍
许多 web 应用需要用户在使用应用之前验证他们的电子邮件地址。 Laravel 提供了方便的内置服务来发送和验证电子邮件验证请求,免去了你在每个应用中手动实现此功能的麻烦。
提示: 想要快速上手?在新的 Laravel 应用中安装一个 Laravel 应用入门套件。入门套件会为你搭建完整的认证系统,包括电子邮件验证支持。
模型准备
首先,检查你的 App\Models\User
模型是否实现了 Illuminate\Contracts\Auth\MustVerifyEmail
合约:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
// ...
}
一旦你的模型添加了这个接口,新注册的用户将会自动收到一个包含电子邮件验证链接的邮件。通过你的应用 App\Providers\EventServiceProvider
,你可以看到 Laravel 已经包含了一个与 Illuminate\Auth\Events\Registered
事件关联的 SendEmailVerificationNotification
监听器,这个事件监听器将会向用户发送电子邮件验证链接。
如果你手动在应用中实现注册,而不使用 入门套件,在用户注册成功后,你应该确保调度了 Illuminate\Auth\Events\Registered
事件:
use Illuminate\Auth\Events\Registered;
event(new Registered($user));
数据库准备
接下来,你的 users
表必须包含一个 email_verified_at
字段,来存储用户的电子邮件地址验证的日期和时间。默认情况下,Laravel 框架自带的 users
表迁移中已包含该字段,所以,你只需运行你的数据库迁移即可:
php artisan migrate
路由
为了正确地实现电子邮件验证,我们需要定义三个路由。
第一,我们需要一个路由来显示提示给用户,提示用户需要点击 Laravel 在注册后发送给他们的电子邮件中的电子邮件验证链接。
第二,我们需要一个路由来处理用户点击电子邮件中的电子邮件验证链接后产生的请求。
第三,当用户不小心丢失了第一封验证链接邮箱时,我们需要一个路由重新发送验证链接。
邮件验证通知
如前所述,应当定义一个路由,返回一个视图,指导用户点击 Laravel 在注册后发给他们的电子邮件中的电子邮件验证链接。当用户尝试访问应用的其他部分,但尚未验证他们的电子邮件地址时,将会显示这个视图。记住,只要你的 App\Models\User
模型实现了 MustVerifyEmail
接口,这个链接就会自动通过电子邮件发送给用户:
Route::get('/email/verify', function () {
return view('auth.verify-email');
})->middleware('auth')->name('verification.notice');
返回电子邮件验证通知的路由应当命名为 verification.notice
。确保此路由正好被赋予了这个名称,因为 Laravel 中的 verified
中间件将自动重定向到此路由名称,如果用户尚未验证他们的电子邮件地址。
提示: 当手动实现电子邮件验证时,你需要自己定义验证通知视图的内容。如果你想要脚手架,包含所有必要的认证和验证视图,你可以看看 Laravel 应用入门套件。
邮件验证处理器
接下来,我们需要定义一个路由,用来处理当用户点击电子邮件中的电子邮件验证链接时产生的请求。该路由应命名为 verification.verify
,并添加 auth
和 signed
中间件:
use Illuminate\Foundation\Auth\EmailVerificationRequest;
Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
$request->fulfill();
return redirect('/home');
})->middleware(['auth', 'signed'])->name('verification.verify');
我们来详细查看一下这个路由。首先,你可以看到我们使用 EmailVerificationRequest
请求类型,而不是典型的 Illuminate\Http\Request
实例。EmailVerificationRequest
是 Laravel 内置的一个 表单请求,该请求将会自动处理验证请求的 id
和 hash
参数。
接下来,我们可以直接调用请求的 fulfill
方法。这个方法将会在已认证的用户上调用 markEmailAsVerified
方法,并调度 Illuminate\Auth\Events\Verified
事件。markEmailAsVerified
方法可以通过 Illuminate\Foundation\Auth\User
基类默认在 App\Models\User
上得到使用。一旦用户的电子邮件地址已经被验证,你可以把他们重定向到你想要的地方。
重发验证邮件
有时候用户可能会误放或意外删除电子邮件地址验证邮件。为了应对这种情况,你可能希望定义一个路由,允许用户请求重新发送验证邮件。然后你可以在你的 验证通知视图 中通过简单的表单提交按钮来请求这个路由:
use Illuminate\Http\Request;
Route::post('/email/verification-notification', function (Request $request) {
$request->user()->sendEmailVerificationNotification();
return back()->with('message', 'Verification link sent!');
})->middleware(['auth', 'throttle:6,1'])->name('verification.send');
保护路由
路由中间件 可用于只允许已经验证的用户访问特定的路由。Laravel 附带了一个 verified
中间件,它是 Illuminate\Auth\Middleware\EnsureEmailIsVerified
类的别名。由于此中间件已经在你应用的 HTTP 内核中注册,你所需要我做的只是在路由定义中添加此中间件。通常,这个中间件会与 auth
中间件配对接使用:
Route::get('/profile', function () {
// 只有已验证的用户可以访问这个路由...
})->middleware(['auth', 'verified']);
如果一个未经验证的用户试图访问已经被分配了此中间件的路由,他们将会自动被重定向到 verification.notice
命名路由。
自定义
验证邮件自定义
尽管默认的电子邮件验证通知应该满足大多数应用的需求,但 Laravel 允许你自定义如何构建电子邮件验证邮件。
首先,将一个闭包传递给 Illuminate\Auth\Notifications\VerifyEmail
通知的 toMailUsing
方法。闭包将会接收一个正在接收通知的可通知模型实例和用户必须访问的已签名的电子邮件验证 URL。闭包应该返回一个 Illuminate\Notifications\Messages\MailMessage
实例。通常,你应该在你的应用 App\Providers\AuthServiceProvider
类的 boot
方法中调用 toMailUsing
方法。
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Notifications\Messages\MailMessage;
/**
* 注册任何认证 / 授权服务。
*/
public function boot(): void
{
// ...
VerifyEmail::toMailUsing(function (object $notifiable, string $url) {
return (new MailMessage)
->subject('Verify Email Address')
->line('Click the button below to verify your email address.')
->action('Verify Email Address', $url);
});
}
提示: 要了解更多关于邮件通知的信息,请参阅 邮件通知文档。
事件
使用 Laravel 应用入门套件 时,Laravel 在电子邮件验证流程中调度 事件。如果你手动处理应用的电子邮件验证,你可能希望在验证完成后手动调度这些事件。你可以将监听器附加到这些事件中,在你的应用的 EventServiceProvider
中:
use App\Listeners\LogVerifiedUser;
use Illuminate\Auth\Events\Verified;
/**
* 应用的事件监听器映射。
*
* @var array
*/
protected $listen = [
Verified::class => [
LogVerifiedUser::class,
],
];
No Comments