Laravel系列之CMS系统学习 — 角色、权限配置【1】

一、后台Admin模块

  后台管理是有管理员的,甚至超级管理员,所以在设计数据表的时候,就会有2个方案,一个方案是共用users数据表,添加is_admin,is_superAdmin字段来进行验证,或者将用户编到不同的组里面,另一个方案是,单独创建admins数据表来进行管理(这样前台和后台是两个事件,前台用户是没有机会操作后台相关功能的,也就是完全隔离了)

  我采用第二种(实习快四个月了,跟了2个完整项目是这样~)

  我在上一篇说到,我使用的是laravel-module,所以相关初始配置不再赘述。

  使用artisan hd:module Admin后,可访问后台界面partTime.com/admin

二、动态分层管理后台菜单

三、创建Guard守卫实现前后台账号分离

  1. 守卫Guard配置

    请仔细看下面代码中的注释~

  1 <?php
  2 
  3 return [
  4 
  5     /*
  6     |--------------------------------------------------------------------------
  7     | Authentication Defaults
  8     |--------------------------------------------------------------------------
  9     |
 10     | This option controls the default authentication "guard" and password
 11     | reset options for your application. You may change these defaults
 12     | as required, but they're a perfect start for most applications.
 13     | defaults:默认使用web守卫者
 14     | guard:守卫者,守卫web(也就是前台的所有操作)
 15     | passwords:守卫者对应的数据表,也即是根据哪一张来进行守卫
 16     |
 17     */
 18 
 19     'defaults' => [
 20         'guard'     => 'web',
 21         'passwords' => 'users',
 22     ],
 23 
 24     /*
 25     |--------------------------------------------------------------------------
 26     | Authentication Guards
 27     |--------------------------------------------------------------------------
 28     |
 29     | Next, you may define every authentication guard for your application.
 30     | Of course, a great default configuration has been defined for you
 31     | here which uses session storage and the Eloquent user provider.
 32     |
 33     | All authentication drivers have a user provider. This defines how the
 34     | users are actually retrieved out of your database or other storage
 35     | mechanisms used by this application to persist your user's data.
 36     |
 37     | Supported: "session", "token"
 38     | 这部分是定义守卫者
 39     | driver:通过什么方式来检索用户,要么session会话,要么token令牌
 40     | provider:对应的数据表
 41     |
 42     */
 43 
 44     'guards' => [
 45         'web'   => [
 46             'driver'   => 'session',
 47             'provider' => 'users',
 48         ],
 49         'admin' => [
 50             'driver'   => 'session',
 51             'provider' => 'admins',
 52         ],
 53 
 54         'api' => [
 55             'driver'   => 'token',
 56             'provider' => 'users',
 57         ],
 58     ],
 59 
 60     /*
 61     |--------------------------------------------------------------------------
 62     | User Providers
 63     |--------------------------------------------------------------------------
 64     |
 65     | All authentication drivers have a user provider. This defines how the
 66     | users are actually retrieved out of your database or other storage
 67     | mechanisms used by this application to persist your user's data.
 68     |
 69     | If you have multiple user tables or models you may configure multiple
 70     | sources which represent each model / table. These sources may then
 71     | be assigned to any extra authentication guards you have defined.
 72     |
 73     | Supported: "database", "eloquent"
 74     | 因为Laravel对数据表的操作都是通过模型Model,所以需要再此定义
 75     | Admin模型定义:php artisan make:model Admin -fm(f代表模型工厂,m代表数据迁移表) 这种方式很方便,比用一个一个去创建了~~不使用此方法的话,万一表定义错了,你还得告诉模型你使用的是拿一张表
 76     |
 77     */
 78 
 79     'providers' => [
 80         'users'  => [
 81             'driver' => 'eloquent',
 82             'model'  => App\User::class,
 83         ],
 84         'admins' => [
 85             'driver' => 'eloquent',
 86             'model'  => App\Admin::class,
 87         ],
 88 
 89         // 'users' => [make
 90         //     'driver' => 'database',
 91         //     'table' => 'users',
 92         // ],
 93     ],
 94 
 95     /*
 96     |--------------------------------------------------------------------------
 97     | Resetting Passwords
 98     |--------------------------------------------------------------------------
 99     |
100     | You may specify multiple password reset configurations if you have more
101     | than one user table or model in the application and you want to have
102     | separate password reset settings based on the specific user types.
103     |
104     | The expire time is the number of minutes that the reset token should be
105     | considered valid. This security feature keeps tokens short-lived so
106     | they have less time to be guessed. You may change this as needed.
107     |
108     */
109 
110     'passwords' => [
111         'users' => [
112             'provider' => 'users',
113             'table'    => 'password_resets',
114             'expire'   => 60,
115         ],
116     ],
117 
118 ];
auth.php

   注意:

    此时创建出来的Admin.php如下,其实是不完整的哟,往下看~

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Admin extends Model
{
    //
}

  2. View、Controller的配置

    View可以使用和前台一样的界面,也可以自己修改界面,无非就是个样式问题

    Controller和前台一样

    所以如果一样的话,直接复制粘贴,修改控制器的namespace就好啦~

    如果你使用了不同UI,却发现界面不对的话,在LoginController添加以下方法

// 这是指定显示哪一个界面
public function showLoginForm()
{
    return view('admin::auth.login');
}

 

  3. 路由配置

    方法一:

1 // middleware中间件
2 // prefix:前缀(可以使用artisan route:list查看)比如:前台登陆:http://parttime.com/login,后台登陆:http://parttime.com/admin/login(其中的admin就是属性prefix指定的)
3 Route::group(
4     ['middleware' => 'web', 'prefix' => 'admin', 'namespace' => 'Modules\Admin\Http\Controllers'],
5     function () {
6         Auth::routes();
7     }
8 );

   如果用这种方式的话,那么form表单的action属性就得写成action="/admin/login"

  方法二:

 1 Route::group(
 2     ['middleware' => 'web', 'prefix' => 'admin', 'namespace' => 'Modules\Admin\Http\Controllers'],
 3     function () {
 4         Route::name('admin.')->group(
 5             function () {
 6                 Auth::routes();
 7             }
 8         );
 9     }
10 );

  如果用这种方式的话,那么form表单的action属性就得写成action="{{route('admin.login')}}"

4. 错误

  错误一:邮箱不能为空

    LoginController中use了一个AuthenticatesUsers,它里面有那个方法username()是指定验证的用户名是谁,默认是email,我们可以对它进行重写

public function username()
{
    return 'name';// 或者你想验证的属性
}

  错误二:用户名密码错误

   为了方便测试,我们将admins表中的第一条数据进行了修改,因此排除Factory、AdminSeeder的错误

   其实AuthenticatesUsers还有一个guard()方法,它指定使用哪一个守卫者,不传参默认使用web,所以需要对它进行重写(也就是告诉网页,此时的url是谁保护的)

protected function guard()
{
    return \Auth::guard('admin');
}

  错误三:好多英文~

    截至目前,Admin.php中只是继承了Model,它只是实现了对表的一些操作,比如增删改查等等,并没有守卫者

    那我们来看一下系统默认的User.php模型是怎么样的

 1 <?php
 2 
 3 namespace App;
 4 
 5 use Illuminate\Notifications\Notifiable;
 6 use Illuminate\Foundation\Auth\User as Authenticatable;
 7 
 8 class User extends Authenticatable
 9 {
10     use Notifiable;
11 
12     /**
13      * The attributes that are mass assignable.
14      *
15      * @var array
16      */
17     protected $fillable = [
18         'name', 'email', 'password',
19     ];
20 
21     /**
22      * The attributes that should be hidden for arrays.
23      *
24      * @var array
25      */
26     protected $hidden = [
27         'password', 'remember_token',
28     ];
29 }
User.php

    我们可以模仿它来改造我们的Admin.php模型

 1 <?php
 2 
 3 namespace App;
 4 
 5 use Illuminate\Notifications\Notifiable;
 6 use Illuminate\Foundation\Auth\User as Authenticatable;
 7 
 8 class Admin extends Authenticatable
 9 {
10     use Notifiable;
11     
12     //
13 }

    搞定,后台也可以登陆啦~ 然后你又会发现一个问题,为啥跳转到了前台登陆界面

  错误四:跳转错误

   其实这里暗藏了两个问题:1.为什么跳转错误(肯定是和后台相关的一些配置出了问题)2.为什么跳转到的是前台的登陆界面

   咱们先解决第2个问题:

     这是前台路由配置,Laravel有中间件机制,当前台用户没有登陆的时候,他访问了网址,就会自动跳转到登陆界面,而控制这个Controller是前台的HomeController.php

 1 <?php
 2 
 3 /*
 4 |--------------------------------------------------------------------------
 5 | Web Routes
 6 |--------------------------------------------------------------------------
 7 |
 8 | Here is where you can register web routes for your application. These
 9 | routes are loaded by the RouteServiceProvider within a group which
10 | contains the "web" middleware group. Now create something great!
11 |
12 */
13 
14 // 主页面
15 Route::get(
16     '/',
17     function () {
18         return view('welcome');
19     }
20 );
21 
22 // 前台登陆、注册、找回密码
23 Auth::routes();
24 
25 Route::get('/home', 'HomeController@index')->name('home');
web.php
 1 <?php
 2 
 3 namespace App\Http\Controllers;
 4 
 5 class HomeController extends Controller
 6 {
 7     /**
 8      * Create a new controller instance.
 9      *
10      * @return void
11      */
12     public function __construct()
13     {
14         $this->middleware('auth');
15     }
16 
17     /**
18      * Show the application dashboard.
19      *
20      * @return \Illuminate\Http\Response
21      */
22     public function index()
23     {
24         return view('home');
25     }
26 }
HomeController.php

  再解决第一个问题:

    很简单,再Admin模块的LoginController.php中,有一个$redirectTo属性就是控制跳转的~

    补充:

      无论前台还是后台,用户登陆成功了以后,再通过地址栏访问登陆界面是不应该出现它的,所以中间件的魅力就可以凸显~

四、中间件设置前后台跳转不同路由

  中间件有Laravel已经配置好的(app/Http/Kernel.php),也可以自己自定义

  前后台的LoginController.php的构造方法如下

1 public function __construct()
2 {
3     $this->middleware('guest')->except('logout');// except:指定的方法或方法组不进行验证
4 }

    guest中间件是对游客的限制,那么就会有一个问题:如何指定这个有可能即将登陆的游客是什么角色呢,是前台用户,还是后台管理员?所以guard守卫者再次派上用场

    middleware('guest:admin')当不指定admin的时候默认采用web(前台)守卫者,否则采用指定的守卫者(这里是admin守卫者)

    那么又产生一个问题:我验证成功了,如何针对不同角色的用户实现不同的跳转呢?

    下面是guest中间件所对应的类实现的方法(暂时忽略$next,这个和设计模式有关,现在还用不到)

      逻辑很简单,判断是否有传进来的守卫者,没有就用默认的web,然后进行跳转/home(问题就在这里:不管前台还是后台都是跳转/home,显然是不对的,因此需要对其进行修改)

 1 <?php
 2 
 3 namespace App\Http\Middleware;
 4 
 5 use Closure;
 6 use Illuminate\Support\Facades\Auth;
 7 
 8 class RedirectIfAuthenticated
 9 {
10     /**
11      * Handle an incoming request.
12      *
13      * @param  \Illuminate\Http\Request  $request
14      * @param  \Closure  $next
15      * @param  string|null  $guard
16      * @return mixed
17      */
18     public function handle($request, Closure $next, $guard = null)
19     {
20         if (Auth::guard($guard)->check()) {
21             return redirect('/home');
22         }
23 
24         return $next($request);
25     }
26 }

    修改后:

 1 <?php
 2 
 3 namespace App\Http\Middleware;
 4 
 5 use Closure;
 6 use Illuminate\Support\Facades\Auth;
 7 
 8 class RedirectIfAuthenticated
 9 {
10     /**
11      * Handle an incoming request.
12      *
13      * @param  \Illuminate\Http\Request $request
14      * @param  \Closure $next
15      * @param  string|null $guard
16      *
17      * @return mixed
18      */
19     public function handle($request, Closure $next, $guard = null)
20     {
21         if (Auth::guard($guard)->check()) {
22             // 可以自行决定跳转到哪里~
23             return redirect($guard == 'admin' ? '/admin' : '/home');
24         }
25 
26         return $next($request);
27     }
28 }

  

AuthenticatesUsers
posted @ 2018-12-04 15:47  李天其  阅读(532)  评论(0编辑  收藏  举报