上一节我们介绍了 Laravel 用户认证系统基本概念,这一节来更深入的了解如何使用。
使用以下命令来快速生成身份认证所需的路由和视图:
php artisan make:auth
该命令会自动创建用户认证相关的控制器:
app/Http/Controllers/Auth/ForgotPasswordController.php - 用于忘记密码后发送找回密码邮件
app/Http/Controllers/Auth/LoginController.php - 用于登录
app/Http/Controllers/Auth/RegisterController.php - 用于注册
app/Http/Controllers/Auth/ResetPasswordController.php - 用于重置密码
同时在路由 routes/web.php
中添加用户认证所需路由:
.
.
.
Auth::routes();
这个方法定义了哪些路由呢?我们一步步来找找。
首先在 config/app.php
中找到 Auth 的 alias:
.
.
.
'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class,
.
.
.
找到 Illuminate\Support\Facades\Auth
这个门面,可以看到里面的 routes
方法:
.
.
.
public static function routes()
{
static::$app->make('router')->auth();
}
.
.
.
这里实例化了一个 Router 类,然后找到对应的 Router 类 Illuminate\Routing\Router
:
.
.
.
public function auth()
{
// Authentication Routes...
$this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
$this->post('login', 'Auth\LoginController@login');
$this->post('logout', 'Auth\LoginController@logout')->name('logout');
// Registration Routes...
$this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
$this->post('register', 'Auth\RegisterController@register');
// Password Reset Routes...
$this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
$this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
$this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
$this->post('password/reset', 'Auth\ResetPasswordController@reset');
}
.
.
.
到这里一切都水落石出了。
如果新用户注册之后,需要给用户发送一个通知,要怎么实现呢?
可以用上一节提到的用监听器来监听指定的事件。
app/Http/Controllers/Auth/RegisterController.php
里引用了 Illuminate\Foundation\Auth\RegistersUsers
这个 trait,注册流程如下:
.
.
.
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());
}
.
.
.
注册成功之后会触发 Illuminate\Auth\Events\Registered
事件,所以我们只需要监听该事件就行了。
新建一个监听器:
php artisan make:listener RegisteredListener
内容如下:
<?php
namespace App\Listeners;
use App\Notifications\EmailVerificationNotification;
use Illuminate\Auth\Events\Registered;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
// implements ShouldQueue 让这个监听器异步执行
class RegisteredListener implements ShouldQueue
{
// 当事件被触发时,对应该事件的监听器的 handle() 方法就会被调用
public function handle(Registered $event)
{
// 获取到刚刚注册的用户
$user = $event->user;
// 调用 notify 发送通知
$user->notify(new EmailVerificationNotification());
}
}
监听器创建完成之后记得在 EventServiceProvider 中将事件和监听器关联起来才能生效:
app/Providers/EventServiceProvider.php
use App\Listeners\RegisteredListener;
use Illuminate\Auth\Events\Registered;
.
.
.
protected $listen = [
Registered::class => [
RegisteredListener::class,
],
];
.
.
.
用户认证自带密码重置功能,当我们输入注册邮箱后,会给该邮箱发送密码重置邮件。如何修改该邮件视图呢?
app/Http/Controllers/Auth/ForgotPasswordController.php
中使用 Illuminate\Foundation\Auth\SendsPasswordResetEmails
trait 来实现该功能。
找到该文件:
.
.
.
public function sendResetLinkEmail(Request $request)
{
$this->validateEmail($request);
// We will send the password reset link to this user. Once we have attempted
// to send the link, we will examine the response then see the message we
// need to show to the user. Finally, we'll send out a proper response.
$response = $this->broker()->sendResetLink(
$request->only('email')
);
return $response == Password::RESET_LINK_SENT
? $this->sendResetLinkResponse($response)
: $this->sendResetLinkFailedResponse($request, $response);
}
.
.
.
由对应的 broker 来发送重置密码的链接。该 broker 正是 Illuminate\Auth\Passwords\PasswordBroker
:
.
.
.
public function sendResetLink(array $credentials)
{
// First we will check to see if we found a user at the given credentials and
// if we did not we will redirect back to this current URI with a piece of
// "flash" data in the session to indicate to the developers the errors.
$user = $this->getUser($credentials);
if (is_null($user)) {
return static::INVALID_USER;
}
// Once we have the reset token, we are ready to send the message out to this
// user with a link to reset their password. We will then redirect back to
// the current URI having nothing set in the session to indicate errors.
$user->sendPasswordResetNotification(
$this->tokens->create($user)
);
return static::RESET_LINK_SENT;
}
.
.
.
调用了 User 类的 sendPasswordResetNotification
方法,并将 token 作为参数传进去。
回到模型 app/Models/User.php
中,它继承自 Illuminate\Foundation\Auth\User
,而该类使用了 CanResetPassword
trait,我们找到了最终调用的方法:
.
.
.
use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification;
trait CanResetPassword
{
/**
* Get the e-mail address where password reset links are sent.
*
* @return string
*/
public function getEmailForPasswordReset()
{
return $this->email;
}
/**
* Send the password reset notification.
*
* @param string $token
* @return void
*/
public function sendPasswordResetNotification($token)
{
$this->notify(new ResetPasswordNotification($token));
}
}
.
.
.
所以要修改邮件内容也很简单了,在 User 类中重写该方法,自定义通知并发送就可以了。