继上文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())));</code> laravel的事件系统,表示触发了<code>Registered</code>事件,打开 <code>app/Providers/EventServiceProvider.php</code> 文件,此文件的 listen 属性里我们可以看到注册了 Registered 事件的监听器:
代码语言:javascript
复制
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
打开
vendor/laravel/framework/src/Illuminate/Auth/Listeners/SendEmailVerificationNotification.php
, 查看具体的监听器代码:
代码语言:javascript
复制
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
设置为:
代码语言:javascript
复制
MAIL_DRIVER=log
然后新注册一个用户,提交表单后,查看
storage/logs/laravel-2019-03-25.log
目录下最新的日志文件,能看到laravel发送的验证内容
image
中间件验证权限
新注册的用户并没有进行邮箱验证,可以通过
dd(\Auth::user()->hasVerifiedEmail());
测试是否已经验证
我们要实现的逻辑是:未验证的用户自动跳转到邮箱验证提示页面。可以借助中间件来实现此功能
代码语言:javascript
复制
php artisan make:middleware EnsureEmailIsVerified</code></pre></div></div><p>自动创建 <code>app/Http/Middleware/EnsureEmailIsVerified.php</code></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">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
image
我们将log文件中的验证链接粘贴到浏览器访问,即可成功验证
小结
邮件认证的功能,laravel已经帮我们封装好了,只需进行简单的调用。难点在于理顺整个逻辑