Laravel 5.3 多用户表登录

教程 lanceWan ⋅ 于 2016-09-07 14:08:40 ⋅ 最后回复由 cky 2017-09-21 09:01:30 ⋅ 9548 阅读

Laravl5.3多用户表登录

关于Laravel5.2多用户表登录文章传送门:http://iwanli.me/article/42

简介

在底层代码中,Laravel 的认证组件由 guardsproviders组成,Guard 定义了用户在每个请求中如何实现认证,例如,Laravel 通过 session guard来维护 Session 存储的状态、Cookie 以及 token guard,token guard 是认证用户发送请求时带的API token。

Provider 定义了如何从持久化存储中获取用户信息,Laravel 底层支持通过 Eloquent 和数据库查询构建器两种方式来获取用户,如果需要的话,你还可以定义额外的 Provider

相对于Laravel5.2而言,Laravel5.3在底层代码中做了很多修改,方法更加简洁,这个下面会提到。虽然代码改了很多,但是原理都是一样的,我们只需要重写不同的方法而已。

默认认证

首先我们使用Laravel 5.3提供的开箱即用的认证:

php artisan make:auth

该Artisan命令会生成用户认证所需的路由、视图以及HomeController:

认证的路由也一并生成好了,查看路由文件routes/web.php,会发现该文件已经被更新:

Auth::routes();

Route::get('/home', 'HomeController@index');

其中Auth::routes()定义了登录注册及找回密码路由,/home 为用户认证成功后跳转的路由。

验证

接下来我们先实现前台用户登录,也就是Laravel自带的Users用户表登录。通过生成的默认登录认证,已经写好了所有代码,剩下要做的就是使用迁移命令创建用户认证相关表:

php artisan migrate

执行命令后会生成 users 表和 password_resets 表,分别为用户表和密码重置表。然后我们就可以在浏览器中输入http://blog.me/register来注册新用户:

我们创建一个 iwanli 的用户,注册成功后直接跳转 /home,并且刚注册的用户名也已经显示出来了:

登录、找回密码功能都已经写好,我就不一一测试了~

自定义用户表登录

首先要看看默认的用户认证配置文件auth.php,配置如下:

<?php
return [
    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
    ],
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'email' => 'auth.emails.password',
            'table' => 'password_resets',
           'expire' => 60,
        ],
    ],
];

认证是由 guardprovider 两部分构成的(参考用户认证文档),defaults 配置是选择哪一个 guard 认证驱动,所以我们在这两个配置项中分别添加一个 adminadmins 选项。

<?php
return [
    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Models\Admin::class,
        ],
    ],
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'email' => 'auth.emails.password',
            'table' => 'password_resets',
           'expire' => 60,
        ],
    ],
];

创建后台用户用户表及Model

接下来我们来实现后台用户登录,使用如下Artisan命令生成后台用户Model:

php artisan make:model Models/Admin -m

带上-m 选项会生成对应迁移文件 *_create_admins_table,我们定义该数据表字段和users一样,你也可以自定义:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateAdminsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('admins', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('admins');
    }
}

由于后台一般只需要登录功能,所以来给 admins 表填充一些数据:

php artisan make:seeder AdminsTableSeeder

执行完命令后将会在 database/seeds 目录下生成 AdminsTableSeeder.php 文件。接下来我们定义一个数据模型工厂,在 database/factories/ModelFactory.php 中添加如下代码:

<?php

/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| Here you may define all of your model factories. Model factories give
| you a convenient way to create models for testing and seeding your
| database. Just tell the factory how a default model should look.
|
*/

$factory->define(App\User::class, function (Faker\Generator $faker) {
    static $password;

    return [
        'name' => $faker->name,
        'email' => $faker->safeEmail,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
    ];
});

$factory->define(App\Models\Admin::class, function (Faker\Generator $faker) {
    static $password;

    return [
        'name' => $faker->name,
        'email' => $faker->safeEmail,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
    ];
});

模型工厂定义完成后,在 AdminsTableSeeder.php 中填充数据:

<?php

use Illuminate\Database\Seeder;

class AdminsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory('App\Models\Admin',3)->create([
            'password' => bcrypt('123456')
            ]);
    }
}

填充数据弄好后,在 DatabaseSeeder.php 中加入 AdminsTableSeeder

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // $this->call(UsersTableSeeder::class);
        $this->call(AdminsTableSeeder::class);
    }
}

最后执行迁移命令:

php artisan migrate --seed

OK,我们在查看数据库:

修改Admin模型类如下:

<?php

namespace App\Models;

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

class Admin 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',
    ];
}

后台用户认证路由及控制器

使用Artisan命令创建控制器:

php artisan make:controller Admin/LoginController
php artisan make:controller Admin/DashboardController

编辑 Admin/LoginController.php ,代码如下:

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login / registration.
     *
     * @var string
     */
    protected $redirectTo = '/admin/dash';
    protected $username;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest:admin', ['except' => 'logout']);
        $this->username = config('admin.global.username');
    }
    /**
     * 重写登录视图页面
     * @author 晚黎
     * @date   2016-09-05T23:06:16+0800
     * @return [type]                   [description]
     */
    public function showLoginForm()
    {
        return view('admin.login.index');
    }
    /**
     * 自定义认证驱动
     * @author 晚黎
     * @date   2016-09-05T23:53:07+0800
     * @return [type]                   [description]
     */
    protected function guard()
    {
        return auth()->guard('admin');
    }
}

LoginController 中我们在构造函数中修改了 guest 中间件,用来跳转不同路由:

  • app\Http\Middleware\RedirectIfAuthenticated.php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

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()) {
            // 根据不同 guard 跳转到不同的页面
            $url = $guard ? 'admin/dash':'/home';
            return redirect($url);
        }

        return $next($request);
    }
}

编辑 Admin/DashboardController.php ,代码如下:

<?php

namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;

class DashboardController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth.admin:admin');
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        dd('后台首页,当前用户名:'.auth('admin')->user()->name);
    }
}

DashboardController 构造函数中我们添加了一个 auth.admin Middleware,这个是我们自定义的,所以我们要来新建一个 Middleware

php artisan make:middleware AdminAuthMiddleware

编辑 AdminAuthMiddleware

<?php

namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class AdminAuthMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next,$guard = null)
    {
        if (Auth::guard($guard)->guest()) {
            if ($request->ajax() || $request->wantsJson()) {
                return response('Unauthorized.', 401);
            } else {
                return redirect()->guest('admin/login');
            }
        }
        return $next($request);
    }
}

app\Http\Kernel.php 中注册:

protected $routeMiddleware = [
    ......
    'auth.admin' => \App\Http\Middleware\AdminAuthMiddleware::class,
    ......
];

routes/web.php 中添加如下路由:

Route::group(['prefix' => 'admin','namespace' => 'Admin'],function ($router)
{
    $router->get('login', 'LoginController@showLoginForm')->name('admin.login');
    $router->post('login', 'LoginController@login');
    $router->post('logout', 'LoginController@logout');

    $router->get('dash', 'DashboardController@index');
});

视图文件创建及修改

最后我们要创建后台用户认证对应视图文件,这里我们简单复制默认用户视图模板并稍作修改即可,复制 resources\views\auth\login.blade.php 文件到并重命名 resources\views\admin\login\index.blade.php

修改resources\views\admin\login\index.blade.php目录下登录及注册表单提交地址:

{{ url('/login') }} -> {{ route('admin.login') }}

OK,在浏览器中访问http://blog.me/admin/login 测试:

点击login,页面跳转到http://blog.me/admin/dash,说明后台登录成功!

OK,至此我们已经完成前后台用户同时登录认证功能。 Enjoy it !

更多关于Laravel的文章请关注我的博客:http://www.iwanli.me

本帖已被设为精华帖!
本帖由 Summer 于 1年前 加精
回复数量: 54
  • Summer MOD A Life-long learner.
    2016-09-07 14:43:52

    这是 5.3 默认的登录注册页面 UI 吗?阿黎

  • lanceWan 走得慢,但不后退...
    2016-09-07 14:47:28

    @Summer 恩 默认的

  • overtrue MOD https://github.com/overtrue
    2016-09-07 16:21:07

    @lanceWan 感谢分享这么高质量的文章,对于新手与我来讲都有很大的帮助,感谢!另外帮忙改了一处:routes\web.php -> routes/web.php, 加油!

  • lanceWan 走得慢,但不后退...
    2016-09-07 16:22:33

    @overtrue :smile: 非常感谢~

  • ruooooooli
    2016-09-07 18:21:35

    大赞

  • Aufree GitHub(Aufree)微博(@李锦发)
    2016-09-07 20:33:55

    这篇文章对新手很有学习参考价值 :+1:

  • zhuzhichao Lalala Demacian !
    2016-09-07 22:16:50

    很厉害,写的这么详细。:+1:

  • jw嘉华 j 了个 w
    2016-09-08 08:01:41

    犹如行云流水一般,楼主博客好漂亮

  • Summer MOD A Life-long learner.
    2016-09-08 09:22:24

    标题错别字 -> Laravl5.3 我已经改过来,博客的你自己改哈

  • lanceWan 走得慢,但不后退...
    2016-09-08 09:23:55

    @Summer 。。。。。看来每次写完要查几次错别字了

  • Summer MOD A Life-long learner.
    2016-09-08 09:25:04

    @lanceWan 哈哈,没事,这种事情经常发生

  • inkeil
    2016-09-08 14:00:30

    还是放一起的好,最好不好区分

  • outman
    2016-09-08 17:58:41

    :+1:

  • Destiny UI 精美、质量超高的技术博客 https://aabvip.com/
    2016-09-18 10:15:15

    :punch: 非常有价值!

  • ilhamxyz I am phper
    2016-09-18 21:57:45

    直接用users表然后给权限不就行了吗

  • lanceWan 走得慢,但不后退...
    2016-09-19 09:08:24

    @ilhamxyz 方法有很多种,这只是其中的一种方案。

  • DolphinBay
    2016-09-23 13:29:39

    阿黎,我是完全按照你的这个流程写的,到最后点击登录提交的时候,提示我页面无法运作,没有做跳转,还停留在admin/login,能大概知道是什么原因吗?

  • lanceWan 走得慢,但不后退...
    2016-09-23 13:35:46

    @DolphinBay 没有截图看看? 这个我也不好直接说哪里问题呀

  • DolphinBay
    2016-09-23 14:18:03

    file 点击登录以后就是这样,难道是表单提价路由的问题。因为有的地方的代码我还不能完全理解。 麻烦了。

  • DolphinBay
    2016-09-23 14:37:18

    @lanceWan 刚才的问题是我写错了一个地方,但是又遇到一个问题就是,点击登录以后确实能跳转到,admin/dash 但是会提示页面无法运作,代码追到AdminAuthMiddleware.php中的handle,就挂掉了。 我按照图片的写法,就可以了。 什么愿意呢?

    file

  • lanceWan 走得慢,但不后退...
    2016-09-23 14:40:38

    @DolphinBay Auth是门面,必须 use Auth 一下才能用 ,或者想你那样加个 \ 就可以了 。或者你还可以用辅助函数 auth($guard)->guest() 也是一样的效果

  • DolphinBay
    2016-09-23 17:32:50

    @lanceWan 非常感谢,已经应用到项目中了。虽然还有个别地方不理解。

  • ChenPHPER
    2016-09-24 11:08:43

    @lanceWan 在修改Admin模型那里,use了这个类,我不能理解,是否可以解释一下?卡在这里好久了
    use Illuminate\Foundation\Auth\User as Authenticatable;
    还下面的继承关系
    class Admin extends Authenticatable

  • mingyun
    2016-09-24 20:24:01

    博主写的非常赞

  • DolphinBay
    2016-09-24 21:03:00

    @lanceWan 还有一个问题请教一下,如果我没有登陆,范文会自动跳转到 XX.com/admin/login, 但是我登陆了以后, 在去访问 xx.com/admin/login,就会跳转到, xx.com/admin/dash 。然后报错,报的是没有admin/dash路由的问题,可是我登陆成功明显跳转的不是这个路由,而且 ,我的代码里面根本就没有 dash 这个关键字,是个是为什么啊 ?

  • lanceWan 走得慢,但不后退...
    2016-09-26 11:39:48

    @ChenPHPER class Admin extends Authenticatable 这个之所以要继承这个类,是因为Laravel认证驱动会检查你的Model必须继承这个类 ,不然会报错。 Authenticatable 实质上还是继承model的,只不过多了一些方法

  • ChenPHPER
    2016-09-26 12:01:23

    还有个问题,use Illuminate\Foundation\Auth\User as Authenticatable;在这里,我model里面是没有User这个模型的,相对应的用户的是Member,这个需要修改什么吗?

  • lanceWan 走得慢,但不后退...
    2016-09-26 12:08:14

    @ChenPHPER 我想你理解错了,这个User并不是你认为的users表,代表的是用户管理吧。这是Laravel的源码:

    <?php
    
    namespace Illuminate\Foundation\Auth;
    
    use Illuminate\Auth\Authenticatable;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Auth\Passwords\CanResetPassword;
    use Illuminate\Foundation\Auth\Access\Authorizable;
    use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
    use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
    use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
    
    class User extends Model implements
        AuthenticatableContract,
        AuthorizableContract,
        CanResetPasswordContract
    {
        use Authenticatable, Authorizable, CanResetPassword;
    }

    源码里面实质还是继承model,只不过实现了一些接口而已。实现接口方法由 Authenticatable, Authorizable, CanResetPassword 这三个 Trait实现,分别处理认证用户,修改密码之类的。所以你不用修改任何东西,只要你继承就行

  • ChenPHPER
    2016-09-26 14:17:29

    @lanceWan ok,明白了。我之前只看了下api文档,没搞明白,现在点通了,谢谢哈~不过我们不是基于jwt认证的吗?为什么还要用laravel底层的东西去实现?

  • 王杰
    2016-09-26 21:25:10

    博主我复制login.blade.php文件后改名为admin目录下login目录下的index.blade.app后访问页面就会报$error这个全局变量没定义,而访问login.blade.php却没有报这个错
    附上报错的图

    file

  • lanceWan 走得慢,但不后退...
    2016-09-27 14:29:57

    @王杰 这个可能是session的问题,你的路由加了中间件web没? 试一下

  • 王杰
    2016-09-27 14:46:19

    @lanceWan 是添加路由的时候没有在web中间件加,不能处理$error全局变量,现在好了,谢啦!!☆⌒(*^-゜)v

  • shawn
    2016-10-11 14:25:30

    请问LoginController中的自定义认证驱动是什么作用?

    protected function guard(){
        return auth()->guard('admin');
    }
  • lanceWan 走得慢,但不后退...
    2016-10-11 14:28:15

    @shawn 这是指定 config/auth.php 中的用那个providers进行认证 默认是使用 users的provider

  • shawn
    2016-10-11 14:31:36

    @lanceWan 就是说这个跟在控制器构造函数中指定是一样的作用是吧

    public function __construction(){
        $this->middleware('auth:admin');
    }
  • lanceWan 走得慢,但不后退...
    2016-10-11 14:32:31

    @shawn 恩 这个中间件也是指定配置中的驱动

  • 周军
    2016-10-22 22:11:24

    php artisan make:controller Admin/LgoinController

    的单词拼写错了
    应该是:
    ···
    php artisan make:controller Admin/LoginController
    ···

  • JINJIALEI
    2016-10-26 00:11:30

    logout的时候为什么直接跳转到 前台的首页,而且后台注销后前台也注销了,前台注销后台也注销了,怎么修改才能前后台各自可以注销

  • lanceWan 走得慢,但不后退...
    2016-10-26 09:13:37

    @周军 谢谢 原谅总打错字:smile:

  • lanceWan 走得慢,但不后退...
    2016-10-26 09:14:25

    @JINJIALEI 注销这个问题的话我还没仔细去看Laravel的方法,有时间我去仔细看看有什么方法解决

  • 贺钧威
    2016-11-28 00:01:20

    参考您的文章,进行了拓展,https://laravel-china.org/topics/3312 里边提到了您的文章,感觉不妥的话可以联系我~

  • lanceWan 走得慢,但不后退...
    2016-11-28 09:24:29

    @贺钧威 没有什么不妥的,对你有帮助就行了~

  • xhh110 面向工资编程
    2016-12-26 15:49:59

    错别字 创建后台login控制器命令的 打错字了

  • lanceWan 走得慢,但不后退...
    2016-12-26 15:51:13

    @xhh110 这个很尴尬,之前有人跟我说了 。 你们知道就行,我就不多说了~~:smile:

  • xhh110 面向工资编程
    2016-12-26 15:54:13

    @lanceWan 可以改一下嘛

  • lanceWan 走得慢,但不后退...
    2016-12-26 15:56:39

    @xhh110 OK,改好了

  • xhh110 面向工资编程
    2016-12-26 19:40:38

    @lanceWan 在blade模板中。。。Auth::User()->name 获取到前台用户名称 后台怎么获取呢??
    还有 Auth::guest() 怎么认证后台的呢???

  • 休闲时间
    2017-03-28 17:02:58
  • 黄爽
    2017-04-07 15:03:55

    为什么Auth::user()取不到数据?

  • 黄爽
    2017-04-07 15:05:02

    你这样做了后,用户数据存在哪里,session中也没有

  • qqjt
    2017-06-12 15:40:11

    @xhh110
    @黄爽 要先指定 guard(非 default 的)用 Auth::guard('admin')->user()

  • xhh110 面向工资编程
    2017-06-13 09:25:59

    @qqjt 这个我会了。就是attempt不能通过无密码认证。。。只能用setLoginId() 来实现我想要的了、。。

  • elesos
    2017-08-09 20:29:54

    不错,实践成功!

  • cky
    2017-09-21 09:01:30

    收藏

暂无评论~~
  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!
Ctrl+Enter