通过内置脚手架快速实现用户认证


今天开始我们将开启用户认证与授权系列,主要规划了以下内容:

  • 通过内置命令快速实现登录认证功能
  • 用户登录注册流程及多字段登录实现
  • 基于多表的用户认证功能实现
  • 基于 API 的用户认证功能实现
  • 用户认证相关事件触发及监听
  • 邮箱验证及找回密码功能实现
  • 不同系统用户单点登录实现
  • 基于 ACL 的用户权限管理实现
  • 基于 RBAC 的用户权限管理实现

希望通过这个系列的学习,可以帮助你彻底掌握 Laravel 框架中用户认证与授权相关功能的实现。首先我们从用户认证开始。

系统自带脚手架

Laravel 框架开箱为我们提供了一些用户认证需要的脚手架代码。包括数据库迁移文件、用户模型、用户认证中间件和控制控制器等。我们先来简单介绍下它们。

数据库迁移

新安装的 Laravel 应用都包含下面两个迁移文件,分别用于创建用户表和密码重置表,这两张表在用户认证与找回密码过程中会用到:

User 模型类

此外,Laravel 框架还在 app 目录下为我们提供了与用户表相对应的模型类 User,在基于 Eloquent 模型驱动的认证提供者中,我们通过该模型类实现登录认证,你可以在配置文件 config/auth.php 中查看相应的配置:

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\User::class,
    ],

    // 'users' => [
    //     'driver' => 'database',
    //     'table' => 'users',
    // ],
],

如果你不是通过 User 模型类进行认证,可以在这里修改对应的 model 配置项。如果你不想通过 Eloquent 模型驱动,而是基于原生的数据库查询,可以注释掉 eloquent 对应的 users 配置,启用下面这个 database 对应的 users 配置,这样的话就是直接去查询 users 表,而不是通过模型类进行认证了。

回到我们的默认配置,我们看下 User 模型类代码:

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

如果某个模型类需要用于认证,必须继承自 Illuminate\Foundation\Auth\User 基类,否则会报错。然后我们在这个模型类中使用了 Notifiable Trait,里面提供了用户发送通知的相关方法。我们在白名单 $fillable 中配置了三个字段,这三个字段会在登录和注册时用到。最后,我们还配置了 $hidden 属性,在返回查询结果的时候将敏感信息过滤掉,避免安全隐患。

认证中间件

Laravel 框架内置了几个认证中间件,用于在需要认证的路由中拒绝未认证用户发起的请求,或者将已登录用户重定向到认证页面,打开 app/Http/Kernel.php,可以在 $routeMiddleware 看到对应的路由中间件:

我们平时主要用到的是 auth 中间件和 guest 中间件,auth.basic 用于基于 HTTP 的简单认证,很少用到,throttle 中间件会在用户多次登录失败时使用,单位登录失败超过指定次数不允许继续发起登录请求,提高系统安全性。

auth 中间件是 \App\Http\Middleware\Authenticate::class 的别名,Authenticate 主要用于将未登录用户重定向到登录页面:

class Authenticate extends Middleware
{
    /**
     * Get the path the user should be redirected to when they are not authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return string
     */
    protected function redirectTo($request)
    {
        return route('login');
    }
}

guest 中间件是 \App\Http\Middleware\RedirectIfAuthenticated::class 的别名,RedirectIfAuthenticated 主要用于将已登录用户重定向到认证后页面,未登录则继续原来的请求:

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->check()) {
            return redirect('/home');
        }

        return $next($request);
    }
}

认证控制器

最后,Laravel 还为我们开箱提供了注册、登录、重置密码、邮箱验证、忘记密码对应的控制器:

其中 ForgotPasswordController 用于忘记密码后通过填写注册邮箱发送重置密码链接,对应逻辑位于 Illuminate\Foundation\Auth\SendsPasswordResetEmails Trait 中。

LoginController 用于用户登录和退出,对应逻辑位于 Illuminate\Foundation\Auth\AuthenticatesUsers Trait 中。

RegisterController 用于新用户注册,对应逻辑位于 Illuminate\Foundation\Auth\RegistersUsers Trait 中。

ResetPasswordController 用于重置密码,对应逻辑位于 Illuminate\Foundation\Auth\ResetsPasswords Trait 中。

上述控制器的构造函数中都应用了 guest 中间件(退出功能除外),表示这些控制器提供的方法都是给未登录用户使用的。

VerificationController 是 Laravel 5.7 新提供的,用于新注册用户邮箱验证,对应逻辑位于 Illuminate\Foundation\Auth\VerifiesEmails Trait 中。关于邮箱验证功能后面单独讲。

如果你的系统不需要用户认证功能的话,大可以把这些控制器和中间件都删掉,否则这些就是「僵尸」代码,占个位置而已,没什么用。不过如果你需要用到用户认证,尤其是通过系统自带的 make:auth 命令快速实现用户认证,这些「僵尸」代码就会像启动了发动机的机器一样,迅速与路由、视图无缝整合到一起,提供完整的用户认证解决方案。

接下来,就让这些控制器、中间件运转起来。

通过 Artisan 命令快速实现注册登录

我们可以自己编写用户认证路由、视图然后对接到这些控制器,提供用户认证功能,不过,Laravel 开箱为我们提供了 Artisan 命令 make:auth,运行该命令可以帮助我们在最短时间内完成认证路由注册和认证视图(兼容 Bootstrap 4)发布,既然如此,为什么不用这个自带的命令呢?而且通过该命令提供的路由和视图可以和上面介绍的脚手架代码无缝对接,不需要编写任何额外的代码就可以让新安装的 Laravel 应用具备用户认证相关功能,这,也许就是原装的好处吧。

好了,废话不多说,下面我们在系统根目录下运行如下命令激活「休眠」的用户认证功能:

php artisan make:auth # 注册认证路由、发布认证视图
php artisan migrate   # 创建认证相关数据表,如果之前已经运行过,可以跳过
npm run dev           # 编译前端资源,如果之前已经运行过,可以跳过

make:auth 命令会在 routes/web.php 中注册以下路由:

Auth::routes();
Route::get('/home', 'HomeController@index')->name('home');

home 路由是用户认证成功后默认跳转路由,Auth::routes() 则包含以下路由定义:

// Authentication Routes...
$this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
$this->post('login', 'Auth\LoginController@login');
$this->post('logout', 'Auth\LoginController@logout')->name('logout');

$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')->name('password.update');

// Email Verification Routes...
$this->get('email/verify', 'Auth\VerificationController@show')->name('verification.notice');
$this->get('email/verify/{id}', 'Auth\VerificationController@verify')->name('verification.verify');
$this->get('email/resend', 'Auth\VerificationController@resend')->name('verification.resend');

此外,该命令还会在 resources/views 下发布以下登录认证相关的视图文件:

  • resources/views/home.blade.php
  • resources/views/layouts/app.blade.php
  • resources/views/auth/login.blade.php
  • resources/views/auth/register.blade.php
  • resources/views/auth/verify.blade.php
  • resources/views/auth/passwords/email.blade.php
  • resources/views/auth/passwords/reset.blade.php

这样,不需要编写任何代码,只需要简单运行几个命令,就可以在 Laravel 应用中实现登录认证功能了。这样,我们点击首页的右上角的登录按钮,就可以进入登录页面了:

当然,如果我们还没有注册用户的话,暂时还不能登录,下一篇教程,我们将演示用户注册与登录功能,并实现同时支持多个字段的登录。


Vote Vote Cancel Collect Collect Cancel

<< 上一篇: 基于 Laravel Permission 扩展包在项目中轻松实现 RBAC 权限管理功能

>> 下一篇: 用户注册登录流程及多字段登录实现