简介

许多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;

    // ...
}

为模型添加该接口后,新注册的用户会自动收到一封包含邮箱验证链接的邮件。这一过程能无缝完成,是因为Laravel自动为Illuminate\Auth\Events\Registered事件注册了Illuminate\Auth\Listeners\SendEmailVerificationNotification监听器。

如果您没有使用入门套件,而是手动在应用中实现注册功能,那么请确保在用户注册成功后触发Illuminate\Auth\Events\Registered事件:

use Illuminate\Auth\Events\Registered;

event(new Registered($user));

数据库准备

接下来,您的users表必须包含email_verified_at列,用于存储用户邮箱地址的验证日期与时间。通常,此列已包含在Laravel默认的0001_01_01_000000_create_users_table.php数据库迁移文件中。

路由

要正确实现邮箱验证,需要定义三条路由。第一条路由用于向用户展示提示,告知他们应点击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事件。默认的App\Models\User模型可通过Illuminate\Foundation\Auth\User基类使用markEmailAsVerified方法。用户邮箱地址验证完成后,您可将其重定向到任意位置。

重发验证邮件

用户有时会遗失或误删邮箱地址验证邮件。为解决这一问题,您可定义一条路由,允许用户请求重发验证邮件。之后,在验证提示视图中添加一个简单的表单提交按钮,即可向该路由发起请求:

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中间件类。由于此别名已由Laravel自动注册,您只需在路由定义中附加verified中间件即可。通常,该中间件会与auth中间件配合使用:

Route::get('/profile', function () {
    // Only verified users may access this route...
})->middleware(['auth', 'verified']);

若未验证用户尝试访问应用了该中间件的路由,系统会自动将其重定向到verification.notice命名路由。

自定义

验证邮件自定义

尽管默认的邮箱验证通知能满足大多数应用的需求,但Laravel允许您自定义邮箱验证邮件内容的构建方式。

开始之前,请向Illuminate\Auth\Notifications\VerifyEmail通知提供的toMailUsing方法传入一个闭包。该闭包会接收接收通知的可通知模型实例,以及用户需访问以验证邮箱的签名邮箱验证URL。闭包应返回Illuminate\Notifications\Messages\MailMessage的实例。通常,您应在应用AppServiceProvider类的boot方法中调用toMailUsing方法:

use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Notifications\Messages\MailMessage;

/**
 * Bootstrap any application services.
 */
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会在邮箱验证过程中触发Illuminate\Auth\Events\Verified事件。如果您在应用中手动处理邮箱验证,可在验证完成后手动触发这些事件。