继上文laravel用户认证,本篇将实现新用户需要邮箱验证才能注册成功
邮箱认证流程
分为两步:
-
发送认证邮件 —— 将附带认证信息的『认证链接』发送到用户邮箱里;
-
检测认证链接 —— 用户打开邮件,点击认证链接进入网站,程序检测 URL 中认证参数的合法性,并渲染对应的页面。
代码实现
将 routes/web.php
的认证路由改为:
Auth::routes(['verify' => true]);
在app/User.php
引入 MustVerifyEmailTrait
即可完成邮箱验证
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Auth\MustVerifyEmail as MustVerifyEmailTrait;
use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements MustVerifyEmailContract
{
use Notifiable, MustVerifyEmailTrait;
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
}
代码解析
分析laravel自带的app/Http/Controllers/Auth/RegisterController.php
,注册调用的是:RegistersUsers
这个trait的register
方法:
vendor/laravel/framework/src/Illuminate/Foundation/Auth/RegistersUsers.php
public function register(Request $request)
{
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
$this->guard()->login($user);
return $this->registered($request, $user)
?: redirect($this->redirectPath());
}
使用 event(new Registered($user = $this->create($request->all())));
laravel的事件系统,表示触发了Registered
事件,打开 app/Providers/EventServiceProvider.php
文件,此文件的 $listen 属性里我们可以看到注册了 Registered 事件的监听器:
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
打开 vendor/laravel/framework/src/Illuminate/Auth/Listeners/SendEmailVerificationNotification.php
, 查看具体的监听器代码:
public function handle(Registered $event)
{
if ($event->user instanceof MustVerifyEmail && ! $event->user->hasVerifiedEmail()) {
$event->user->sendEmailVerificationNotification();
}
}
因此只需要满足$event->user instanceof MustVerifyEmail && ! $event->user->hasVerifiedEmail()
即可实现邮件认证功能
测试认证
开发环境中,可以将邮件内容写到日志中,便于调试。将 .env
的 MAIL_DRIVER
设置为:
MAIL_DRIVER=log
然后新注册一个用户,提交表单后,查看storage/logs/laravel-2019-03-25.log
目录下最新的日志文件,能看到laravel发送的验证内容

中间件验证权限
新注册的用户并没有进行邮箱验证,可以通过 dd(\Auth::user()->hasVerifiedEmail());
测试是否已经验证
我们要实现的逻辑是:未验证的用户自动跳转到邮箱验证提示页面。可以借助中间件来实现此功能
$ php artisan make:middleware EnsureEmailIsVerified
自动创建 app/Http/Middleware/EnsureEmailIsVerified.php
public function handle($request, Closure $next)
{
// 判断用户是否需要邮箱验证
// 1. 用户已登录
// 2. 未认证Email
// 3. 访问的不是email验证相关url或者退出的url
if ($request->user() && !$request->user()->hasVerifiedEmail() && !$request->is('email/*', 'logout')) {
return $request->expectsJson() ? abort(403, '您的邮箱尚未验证') : redirect()->route('verification.notice');
}
return $next($request);
}
此时,我们再访问 http://www.test.com/home
,代码经由中间件时,符合邮箱验证条件,因此会被自动跳转到 http://www.test.com/email/verify

我们将log文件中的验证链接粘贴到浏览器访问,即可成功验证
小结
邮件认证的功能,laravel已经帮我们封装好了,只需进行简单的调用。难点在于理顺整个逻辑
网友评论