欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-09-03 23:46:54
一、RBAC分析 基于角色的权限访问控制(Role-Based Access Control),这里存在这么几个玩意儿:角色、权限,用户 表:roles、permissions、role_has_permissions、model_has_roles、model_has_permissions(最后 ......

一、rbac分析

  基于角色的权限访问控制(role-based access control),这里存在这么几个玩意儿:角色、权限,用户

  表:roles、permissions、role_has_permissions、model_has_roles、model_has_permissions(最后两张表可以看4.1有解释)

  明确:用户属于什么角色,那么角色拥有什么权限,用户自然拥有

  然后配置,就(后面就不添加了)~

二、角色的增删改查

  这个就很普通的功能了,略???

  但是有一些需要注意的地方:

    1. 更新操作时,method使用put

    2. laravel的唯一性验证举例:'title' => 'required|unique:roles,title,'.$id,

      解释:对title字段进行验证——必填|唯一性验证:从拿一张表进行验证,验证什么字段,不验证当前字段(意思就是:比如你要修改的信息叫张三,表里面只有你当前编辑的这条记录是张三,所以忽略要这条记录,不然不就不唯一了嘛~)

    3.laravel再进行更新、删除操作时,需要进行传参(也就是你要删除那一条记录的唯一标识),而要想获取这个参数可以使用:$this->route('xxx')

三、权限(很重要,自学的过程中卡了好久)

  控制权限的方式有很多种,但我个人认为,(也是组长要求哈哈哈哈)最合适的方式是中间件

  1. 路由定义

1 // 权限管理
2 route::get('role/permission/{role}', 'rolecontroller@permission');//页面显示
3 route::post('role/permission/{role}', 'rolecontroller@permissionstore');//提交表单

  2. 页面展示

  无论通过modals还是页面来显示权限页面都可以,我觉得少的话使用modals(注意使用modals的话,就不用show方法了),多的话页面展示

  然后就是遍历权限,有两种方法

  方法一:遍历permission.php文件

  方法二:通过方法来获取

1 public function permission(role $role)
2 {
3     // 根据guard来获取权限
4     $modules = \hdmodule::getpermissionbyguard('admin');
5 
6     // 分配  
7     // 之所以分配role是因为1.要进行checkbox选中判断,也就是判断当前用户是否有某权限  2.提交表单role_id
8     return view('admin::role.permission', compact('role'), compact('modules'));
9 }

      然后就可以进行页面渲染了,@foreach就好啦~  里面的一大堆input只是样式啦~

Laravel系列之CMS系统学习 — 角色、权限配置【2】
 1 @extends('admin::layouts.master')
 2 @section('content')
 3     @component('components.tabs',['title'=>$role->title.'权限设置'])
 4         @slot('nav')
 5             <li class="nav-item"><a href="/admin/role" class="nav-link">角色列表</a></li>
 6             <li class="nav-item"><a href="#" class="nav-link active">权限设置</a></li>
 7         @endslot
 8         @slot('body')
 9             <form action="/admin/role/permission/{{$role['id']}}" method="post">
10                 @csrf
11                 @foreach($modules as $module)
12                     <div class="card-body pb-0">
13                         @foreach($module['rules'] as $rule)
14                             <div class="card card-flat">
15                                 <div class="card-header">{{$rule['group']}}</div>
16                                 <div class="col-12 col-sm-8 col-lg-6 form-check mt-2">
17                                     @foreach($rule['permissions'] as $k=>$permission)
18                                         <p hidden>{{$i = $k + rand(0,1000000)}}</p>
19                                         <div class="checkboxwrapper theme3 extrasmallcheckboxsize mr-3"
20                                              style="float: left;">
21                                             <input type="checkbox" name="name[]" id="sample{{$i}}"
22                                                    {{$role->haspermissionto($permission['name'])?'checked=""':''}} value="{{$permission['name']}}">
23                                             <label for="sample{{$i}}">
24                                                 <i>
25                                                     <svg version="1.1" id="layer_1" xmlns="http://www.w3.org/2000/svg"
26                                                          xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
27                                                          width="50px" height="50px" viewbox="0 0 50 50"
28                                                          enable-background="new 0 0 50 50" xml:space="preserve">
29                     <circle fill="none" stroke="#b7b7b7" stroke-width="3" stroke-miterlimit="10" cx="25.11" cy="24.883"
30                             r="23.519"/>
31                                                         <path fill="none" stroke-width="3" stroke-miterlimit="10" d="m48.659,25c0,12.998-10.537,23.534-23.534,23.534
32                     s1.591,37.998,1.591,25s12.127,1.466,25.125,1.466c9.291,0,17.325,5.384,21.151,13.203l19,36l-9-14"/>
33                 </svg>
34                                                 </i>
35                                                 <span style="float: right;margin-top: 3px;font-size: 14px;margin-left: 5px">{{$permission['title']}}</span>
36                                             </label>
37                                         </div>
38                                     @endforeach
39                                 </div>
40                             </div>
41                         @endforeach
42                     </div>
43                 @endforeach
44                 <button class="btn btn-primary">保存</button>
45             </form>
46         @endslot
47     @endcomponent
48 @endsection
permiss.blade.php

3. 给用户设置权限

1 public function permissionstore(request $request, role $role)
2 {
3     $role->syncpermissions($request->name); // 同步权限
4     session()->flash('success', '修改权限成功');
5 
6     return back();
7 }

4. 根据用户来控制后台侧边导航栏的显示

  4.1 初始化管理员角色

    4.1.1 分配角色 —— 角色属于那个模型

      解释:因为cms系统是多模块的,那么角色就得和不同模块绑定关系,不绑定就不可能操作该模块

      $user->assignrole(['super_user', 'admin']);

      注意:laravel默认是没有这方法的,所以需要拓展模型(模拟多继承)

 1 <?php
 2 
 3 namespace app;
 4 
 5 use illuminate\notifications\notifiable;
 6 use illuminate\foundation\auth\user as authenticatable;
 7 use spatie\permission\traits\hasroles;
 8 
 9 class admin extends authenticatable
10 {
11     use notifiable;
12     use hasroles;
13 }

  4.2 侧边导航栏显示

    目的:给用户分配了什么权限,侧边导航栏就显示相应的权限链接

    实现:

      1. 再config文件当中,将menus.php 和 permission.php 的 permission配置项进行统一

      2. 修改_menus.blade.php文件

 1 <div class="left-sidebar-scroll">
 2     <div class="left-sidebar-content">
 3         <ul class="sidebar-elements">
 4             @foreach(\hdmodule::getmenus() as $modulename => $groups)
 5                 @foreach($groups as $group)
 6                     <li class="divider">{{$group['title']}}</li>
 7                     <li class="parent open">
 8                         <a href="#"><i class="{{$group['icon']}}"></i>&nbsp;<span>{{$group['title']}}</span></a>
 9                         <ul class="sub-menu">
10                             @foreach($group['menus'] as $menu)
11                                 @can($menu['permission'])
12                                     <li>
13                                         <a href="{{$menu['url']}}" pjax><i
14                                                     class="{{$menu['icon']}}"></i><span>&nbsp;{{$menu['title']}}</span></a>
15                                     </li>
16                                 @endcan
17                             @endforeach
18                         </ul>
19                     </li>
20                 @endforeach
21             @endforeach
22         </ul>
23     </div>
24 </div>

        解释:@can是laravel的指令,用来检查用户是否具有某种权限

5. 站长权限(超级管理员权限)

  5.1 对laravel-permission的致敬

    我使用的laravel-module中是有对laravel-permission的一个改良,比如对中间件验证权限的改良(larave-permission处理不够灵活并对资源控制器支持不好)

    laravel-module:

     1. 在进行store和update的权限验证时,会自动对跳转到create、edit进行验证

     2. 在进行站长权限判断时,一步即可(而laravel-permission需要先进行用户属于什么角色判断,再进行有什么权限判断两步)

  5.2 修改config/menus.php和config/permission.php文件

    之前在这两个文件中,对permission配置项进行了语义化的书(比如admin模块下的角色管理中的permission配置项写的是admin::config-roles),但其实这2个文件并不对用户开放,且一旦系统成型修改不大,所以运用了以下写法

Laravel系列之CMS系统学习 — 角色、权限配置【2】
 1 <?php return [
 2     0 =>
 3         [
 4             'title'      => '系统管理',
 5             'icon'       => 'fa fa-navicon',
 6             'permission' => ['modules\admin\http\controllers\rolecontroller@index'],
 7             'menus'      =>
 8                 [
 9                     [
10                         'title'      => '角色管理',
11                         'icon'       => 'fa fa-user-md',
12                         'permission' => 'modules\admin\http\controllers\rolecontroller@index',
13                         'url'        => '/admin/role',
14                     ],
15                 ],
16         ],
17 ];
menus.php
Laravel系列之CMS系统学习 — 角色、权限配置【2】
 1 <?php
 2 /**
 3  * 权限配置
 4  * 为了避免其他模块有同名的权限,权限标识要以 '控制器@方法' 开始
 5  */
 6 return [
 7     [
 8         'group'       => '角色管理',
 9         'permissions' => [
10             [
11                 'title' => '角色列表',
12                 'name'  => 'modules\admin\http\controllers\rolecontroller@index',
13                 'guard' => 'admin',
14             ],
15             [
16                 'title' => '添加角色',
17                 'name'  => 'modules\admin\http\controllers\rolecontroller@create',
18                 'guard' => 'admin',
19             ],
20             [
21                 'title' => '删除角色',
22                 'name'  => 'modules\admin\http\controllers\rolecontroller@destory',
23                 'guard' => 'admin',
24             ],
25             [
26                 'title' => '修改角色',
27                 'name'  => 'modules\admin\http\controllers\rolecontroller@edit',
28                 'guard' => 'admin',
29             ],
30             [
31                 'title' => '修改角色权限',
32                 'name'  => 'modules\admin\http\controllers\rolecontroller@permission',
33                 'guard' => 'admin',
34             ],
35         ],
36     ],
37 ];
permission.php

  修改之后,相应的_menus.blade.php也需要进行修改

Laravel系列之CMS系统学习 — 角色、权限配置【2】
 1 <div class="left-sidebar-scroll">
 2     <div class="left-sidebar-content">
 3         <ul class="sidebar-elements">
 4             @foreach(\hdmodule::getmenus() as $modulename => $groups)
 5                 @foreach($groups as $group)
 6                     <li class="divider">{{$group['title']}}</li>
 7                     <li class="parent">
 8                         @if(\hdmodule::hadpermission($group['permission'],'admin'))
 9                             <a href="#"><i class="{{$group['icon']}}"></i>&nbsp;<span>{{$group['title']}}</span></a>
10                             <ul class="sub-menu">
11                                 @foreach($group['menus'] as $menu)
12                                     @if(\hdmodule::hadpermission($menu['permission'],'admin'))
13                                         <li>
14                                             <a href="{{$menu['url']}}" pjax><i
15                                                         class="{{$menu['icon']}}"></i><span>&nbsp;{{$menu['title']}}</span></a>
16                                         </li>
17                                     @endif
18                                 @endforeach
19                             </ul>
20                     </li>
21                     @endif
22                 @endforeach
23             @endforeach
24         </ul>
25     </div>
26 </div>
_menus.blade.php

  5.3 站长权限配置

    整个站都是属于他/她的,所以不需要对其进行验证

   5.3.1 确定站长

    运行 php artisan vender:publish --provider="houdunwang\module\laravelserviceprovider"

   在config/hd_module中就会有webmaster配置项啦

  5.3.2 忽略检测站长权限

    只需要将用户标识和webmaster配置项对应即可

  5.3.3 添加中间件

    在进行后台的任何操作时候,就需要进行中间件来判断是否该用户是站长

    此时就需要路由

 1 <?php
 2 
 3 route::group(
 4     ['middleware' => 'web', 'prefix' => 'admin', 'namespace' => 'modules\admin\http\controllers'],
 5     function () {
 6         auth::routes();
 7     }
 8 );
 9 
10 route::group(
11     ['middleware' => ['web', 'auth:admin'], 'prefix' => 'admin', 'namespace' => 'modules\admin\http\controllers'],
12     function () {
13         // 后台首页
14         route::get('/', 'admincontroller@index');
15 
16         // 角色管理
17         route::resource('role', 'rolecontroller')->middleware('permission:superadmin');
18 
19         // 权限管理
20         route::get('role/permission/{role}', 'rolecontroller@permission')->middleware('permission:superadmin');
21         route::post('role/permission/{role}', 'rolecontroller@permissionstore')->middleware('permission:superadmin');
22     }
23 );

    注意:

      1. 这个中间件是路由中间件,所以需要到app/http/kernel.php中进行注册(之后所以自定义的中间件都是如此,只是需要注册在相应位置即可)

      2. middleware('permission:admin');中的admin参数是守卫者不是webmaster配置项

      3.middleware('permission:admin,resource');中的resource参数时针对resource路由才添加

        'permission' => \houdunwang\module\middlewares\permissionmiddleware::class,

6. 零碎

  6.1 修复vue模板中不能使用js的情况

    需要使用@yield("")占位符,不然会报vue模板错误

  6.2 模型删除操作和表外键约束注意事项

    站长可不敢删除啊

    依赖表数据变化,本表数据删除