原文出处

auth提供了很方便的登录体系,已经做到了开箱即用的便捷,但是任何方便的工具都是需要花费学习成本的,了解的过程就由些痛苦了:)

本着松鼠过冬的原则,自己是能写一点是一点,以后忘记的话也能立即捡起来

安装auth系统

1
php artisan make:auth

默认会安装基于user表的登录验证,现在我们需要增加另一个表的登录验证(比如后台的数据表) 编辑config/auth.php,我们需要指定的就是guardsproviders这两个数组,

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
<?php

return [

   /*
   |--------------------------------------------------------------------------
   | Authentication Defaults
   |--------------------------------------------------------------------------
   |
   | This option controls the default authentication "guard" and password
   | reset options for your application. You may change these defaults
   | as required, but they're a perfect start for most applications.
   |
   */

   'defaults' => [
       'guard' => 'web',
       'passwords' => 'users',
   ],

   /*
   |--------------------------------------------------------------------------
   | Authentication Guards
   |--------------------------------------------------------------------------
   |
   | Next, you may define every authentication guard for your application.
   | Of course, a great default configuration has been defined for you
   | here which uses session storage and the Eloquent user provider.
   |
   | All authentication drivers have a user provider. This defines how the
   | users are actually retrieved out of your database or other storage
   | mechanisms used by this application to persist your user's data.
   |
   | Supported: "session", "token"
   |
   */

   'guards' => [
       //......//
       //这里新加的一组配置,provider的配置在下面有
       'admin' => [
           'driver' => 'session',
           'provider' => 'admin',
       ],
       //.......//
   ],

   /*
   |--------------------------------------------------------------------------
   | User Providers
   |--------------------------------------------------------------------------
   |
   | All authentication drivers have a user provider. This defines how the
   | users are actually retrieved out of your database or other storage
   | mechanisms used by this application to persist your user's data.
   |
   | If you have multiple user tables or models you may configure multiple
   | sources which represent each model / table. These sources may then
   | be assigned to any extra authentication guards you have defined.
   |
   | Supported: "database", "eloquent"
   |
   */

   'providers' => [
       //.............//

       //这就是新加的配置,我们指定了 Admin 这个模型
       'admin' => [
           'driver' => 'eloquent',
           'model' => App\Models\Admin::class,
       ],

       //.............//
   ],

   /*
   |--------------------------------------------------------------------------
   | Resetting Passwords
   |--------------------------------------------------------------------------
   |
   | You may specify multiple password reset configurations if you have more
   | than one user table or model in the application and you want to have
   | separate password reset settings based on the specific user types.
   |
   | The expire time is the number of minutes that the reset token should be
   | considered valid. This security feature keeps tokens short-lived so
   | they have less time to be guessed. You may change this as needed.
   |
   */

   'passwords' => [
       'users' => [
           'provider' => 'users',
           'table' => 'password_resets',
           'expire' => 60,
       ],
   ],

];

新建模型 App/Models/Admin

1
php artisan make:model Models/Admin -m

编辑模型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

namespace App\Models;

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


//这里继承了auth的验证模型 其实和User的一样
class Admin extends Authenticatable
{
   use Notifiable;
   protected $table='admin';
   public $timestamps = false;
   protected $primaryKey = 'id';

   protected $fillable = [
       'name', 'email', 'password',
   ];

   protected $hidden = [
       'password', 'remember_token',
   ];
}

编辑数据迁移文件 database/migrations/xxxx_admin_table.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php

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

/**
* Migration auto-generated by Sequel Pro Laravel Export
* @see https://github.com/cviebrock/sequel-pro-laravel-export
*/
class CreateAdminTable extends Migration
{
   /**
    * Run the migrations.
    *
    * @return void
    */
   public function up()
   {
       Schema::create('admin', 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('admin');
   }
}

编辑数据填充文件,这一步懒得折腾可以直接手动添加数据

编辑 Faker 这个数据模拟的类 database/factories/ModelFactory.php 添加一下内容,是根据我们刚创建的Models/Admin模型而填充的内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
//other code...........

$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),
   ];
});

编辑database/seeds/AdminTableSeeder.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?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')
       ]);
   }
}

将自动填充文件写入总的Seeder文件当中

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
//in database/seeds/DatabaseSeeder.php

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

执行数据库迁移操作 --seed 顺便执行数据填充操作

1
php artisan migrate --seed

好了,到这一步数据库就已经有了admin 这个表,而且里面出现了三条测试数据,我们接着看看控制器里是怎么操作的:

首先创建相应的控制器:

1
2
php artisan make:controller Admin/LoginController
php artisan make:controller Admin/HomeController

Admin/LoginController.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?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');
   }
   /**
    * 重写登录视图页面
    */
   public function showLoginForm()
   {
       return view('admin.login.index');
   }
   /**
    * 自定义认证驱动
    */
   protected function guard()
   {
       return auth()->guard('admin');
   }

   /**
    * 重写方法,让验证字段改成name 而不是默认的email
    */
//    protected function username(){
//        return 'name';
//    }
}

Admin/HomeController.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php

namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;

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

class HomeController 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);
   }
}

因为在LoginController中也使用了 guest这个中间件,而系统自带的那个也使用了它,因此需要在这个中间件里面做一下区分

编辑 app/Http/Kernel.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public function handle($request, Closure $next, $guard = null)
   {
       if (Auth::guard($guard)->check()) {
//            return redirect('/home');
           $url = $guard ? 'admin/dash':'/home';
           return redirect($url);
       }

       return $next($request);
   }

而在 Admin/HomeController这里,因为验证需要登录才能进入,我们给他也加了一个验证中间件 AdminAuthMiddlware

1
php artisan make:middleware AdminAuthMiddlware

编辑AdminAuthMiddlware

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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);
   }
}

在路由文件里添加对应的路由

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// in 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->any('logout', 'LoginController@logout');

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

做到这一步其实就已经算是完成了,剩下的视图部分可以按照resources/views/auth中的内容创建一个resource/views/admin目录,resource/views/admin/login/index.blade.php就是后台登录界面,注意这里的表单提交地址要按刚才路由文件中写的指向后台的登录控制器中,route('admin.login')

这一段是我按照原文操作一遍后自己写了一遍,算是了解了auth的大致运行过程,其后就是翻一下源码进行解析了,为了controller中的代码好看一点其后的运作并不少,但是解耦做的非常不错