一, RBAC 分析
基于角色的权限访问控制 (Role-Based Access Control), 这里存在这么几个玩意儿: 角色, 权限, 用户
表: roles,permissions,role_has_permissions,model_has_roles,model_has_permissions(最后两张表可以看 4.1 有解释)
明确: 用户属于什么角色, 那么角色拥有什么权限, 用户自然拥有
然后配置, 就戳这里 https://github.com/houdunwang/laravel-module (后面就不添加了)~
二, 角色的增删改查
这个就很普通的功能了, 略???
但是有一些需要注意的地方:
1. 更新操作时, method 使用 PUT
2. Laravel 的唯一性验证举例:'title' => 'required|unique:roles,title,'.$id,
解释: 对 title 字段进行验证 -- 必填 | 唯一性验证: 从拿一张表进行验证, 验证什么字段, 不验证当前字段 (意思就是: 比如你要修改的信息叫张三, 表里面只有你当前编辑的这条记录是张三, 所以忽略要这条记录, 不然不就不唯一了嘛~)
3.Laravel 再进行更新, 删除操作时, 需要进行传参 (也就是你要删除那一条记录的唯一标识), 而要想获取这个参数可以使用:$this->route('XXX')
三, 权限 (很重要, 自学的过程中卡了好久)
控制权限的方式有很多种, 但我个人认为,(也是组长要求哈哈哈哈) 最合适的方式是中间件
1. 路由定义
- // 权限管理
- Route::get('role/permission/{role}', 'RoleController@permission');// 页面显示
- Route::post('role/permission/{role}', 'RoleController@permissionStore');// 提交表单
2. 页面展示
无论通过 Modals 还是页面来显示权限页面都可以, 我觉得少的话使用 Modals(注意使用 Modals 的话, 就不用 show 方法了), 多的话页面展示
然后就是遍历权限, 有两种方法
方法一: 遍历 permission.PHP 文件
方法二: 通过方法来获取
- public function permission(Role $role)
- {
- // 根据 guard 来获取权限
- $modules = \HDModule::getPermissionByGuard('admin');
- // 分配
- // 之所以分配 role 是因为 1. 要进行 checkbox 选中判断, 也就是判断当前用户是否有某权限 2. 提交表单 role_id
- return view('admin::role.permission', compact('role'), compact('modules'));
- }
然后就可以进行页面渲染了,@foreach 就好啦~ 里面的一大堆 input 只是样式啦~
- @extends('admin::layouts.master')
- @section('content')
- @component('components.tabs',['title'=>$role->title.'权限设置'])
- @slot('nav')
- <li class="nav-item"><a href="/admin/role" class="nav-link"> 角色列表 </a></li>
- <li class="nav-item"><a href="#" class="nav-link active"> 权限设置 </a></li>
- @endslot
- @slot('body')
- <form action="/admin/role/permission/{{$role['id']}}" method="post">
- @csrf
- @foreach($modules as $module)
- <div class="card-body pb-0">
- @foreach($module['rules'] as $rule)
- <div class="card card-flat">
- <div class="card-header">{{$rule['group']}}</div>
- <div class="col-12 col-sm-8 col-lg-6 form-check mt-2">
- @foreach($rule['permissions'] as $k=>$permission)
- <p hidden>{{$i = $k + rand(0,1000000)}}</p>
- <div class="checkboxWrapper theme3 extraSmallCheckboxSize mr-3"
- style="float: left;">
- <input type="checkbox" name="name[]" id="sample{{$i}}"
- {{$role->hasPermissionTo($permission['name'])?'checked=""':''}} value="{{$permission['name']}}">
- <label for="sample{{$i}}">
- <i>
- <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="50px" height="50px" viewBox="0 0 50 50"
- enable-background="new 0 0 50 50" xml:space="preserve">
- <circle fill="none" stroke="#B7B7B7" stroke-width="3" stroke-miterlimit="10" cx="25.11" cy="24.883"
- r="23.519"/>
- <path fill="none" stroke-width="3" stroke-miterlimit="10" d="M48.659,25c0,12.998-10.537,23.534-23.534,23.534
- 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"/>
- </svg>
- </i>
- <span style="float: right;margin-top: 3px;font-size: 14px;margin-left: 5px">{{$permission['title']}}</span>
- </label>
- </div>
- @endforeach
- </div>
- </div>
- @endforeach
- </div>
- @endforeach
- <button class="btn btn-primary"> 保存 </button>
- </form>
- @endslot
- @endcomponent
- @endsection
- permiss.blade.PHP
3. 给用户设置权限
- public function permissionStore(Request $request, Role $role)
- {
- $role->syncPermissions($request->name); // 同步权限
- session()->flash('success', '修改权限成功');
- return back();
- }
4. 根据用户来控制后台侧边导航栏的显示
4.1 初始化管理员角色
4.1.1 分配角色 -- 角色属于那个模型
解释: 因为 CMS 系统是多模块的, 那么角色就得和不同模块绑定关系, 不绑定就不可能操作该模块
$user->assignRole(['super_user', 'admin']);
注意: Laravel 默认是没有这方法的, 所以需要拓展模型 (模拟多继承)
- <?PHP
- namespace App;
- use Illuminate\Notifications\Notifiable;
- use Illuminate\Foundation\Auth\User as Authenticatable;
- use Spatie\Permission\Traits\HasRoles;
- class Admin extends Authenticatable
- {
- use Notifiable;
- use HasRoles;
- }
4.2 侧边导航栏显示
目的: 给用户分配了什么权限, 侧边导航栏就显示相应的权限链接
实现:
1. 再 Config 文件当中, 将 menus.PHP 和 permission.PHP 的 permission 配置项进行统一
2. 修改_menus.blade.PHP 文件
- <div class="left-sidebar-scroll">
- <div class="left-sidebar-content">
- <ul class="sidebar-elements">
- @foreach(\HDModule::getMenus() as $moduleName => $groups)
- @foreach($groups as $group)
- <li class="divider">{{$group['title']}}</li>
- <li class="parent open">
- <a href="#"><i class="{{$group['icon']}}"></i> <span>{{$group['title']}}</span></a>
- <ul class="sub-menu">
- @foreach($group['menus'] as $menu)
- @can($menu['permission'])
- <li>
- <a href="{{$menu['url']}}" pjax><i
- class="{{$menu['icon']}}"></i><span> {{$menu['title']}}</span></a>
- </li>
- @endcan
- @endforeach
- </ul>
- </li>
- @endforeach
- @endforeach
- </ul>
- </div>
- </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 个文件并不对用户开放, 且一旦系统成型修改不大, 所以运用了以下写法
- <?PHP return [
- 0 =>
- [
- 'title' => '系统管理',
- 'icon' => 'fa fa-navicon',
- 'permission' => ['Modules\Admin\Http\Controllers\RoleController@index'],
- 'menus' =>
- [
- [
- 'title' => '角色管理',
- 'icon' => 'fa fa-user-md',
- 'permission' => 'Modules\Admin\Http\Controllers\RoleController@index',
- 'url' => '/admin/role',
- ],
- ],
- ],
- ];
menus.PHP
- <?PHP
- /**
- * 权限配置
- * 为了避免其他模块有同名的权限, 权限标识要以 '控制器 @方法' 开始
- */
- return [
- [
- 'group' => '角色管理',
- 'permissions' => [
- [
- 'title' => '角色列表',
- 'name' => 'Modules\Admin\Http\Controllers\RoleController@index',
- 'guard' => 'admin',
- ],
- [
- 'title' => '添加角色',
- 'name' => 'Modules\Admin\Http\Controllers\RoleController@create',
- 'guard' => 'admin',
- ],
- [
- 'title' => '删除角色',
- 'name' => 'Modules\Admin\Http\Controllers\RoleController@destory',
- 'guard' => 'admin',
- ],
- [
- 'title' => '修改角色',
- 'name' => 'Modules\Admin\Http\Controllers\RoleController@edit',
- 'guard' => 'admin',
- ],
- [
- 'title' => '修改角色权限',
- 'name' => 'Modules\Admin\Http\Controllers\RoleController@permission',
- 'guard' => 'admin',
- ],
- ],
- ],
- ];
permission.PHP
修改之后, 相应的_menus.blade.PHP 也需要进行修改
- <div class="left-sidebar-scroll">
- <div class="left-sidebar-content">
- <ul class="sidebar-elements">
- @foreach(\HDModule::getMenus() as $moduleName => $groups)
- @foreach($groups as $group)
- <li class="divider">{{$group['title']}}</li>
- <li class="parent">
- @if(\HDModule::hadPermission($group['permission'],'admin'))
- <a href="#"><i class="{{$group['icon']}}"></i> <span>{{$group['title']}}</span></a>
- <ul class="sub-menu">
- @foreach($group['menus'] as $menu)
- @if(\HDModule::hadPermission($menu['permission'],'admin'))
- <li>
- <a href="{{$menu['url']}}" pjax><i
- class="{{$menu['icon']}}"></i><span> {{$menu['title']}}</span></a>
- </li>
- @endif
- @endforeach
- </ul>
- </li>
- @endif
- @endforeach
- @endforeach
- </ul>
- </div>
- </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 添加中间件
在进行后台的任何操作时候, 就需要进行中间件来判断是否该用户是站长
此时就需要路由
- <?PHP
- Route::group(
- ['middleware' => 'web', 'prefix' => 'admin', 'namespace' => 'Modules\Admin\Http\Controllers'],
- function () {
- Auth::routes();
- }
- );
- Route::group(
- ['middleware' => ['web', 'auth:admin'], 'prefix' => 'admin', 'namespace' => 'Modules\Admin\Http\Controllers'],
- function () {
- // 后台首页
- Route::get('/', 'AdminController@index');
- // 角色管理
- Route::resource('role', 'RoleController')->middleware('permission:superAdmin');
- // 权限管理
- Route::get('role/permission/{role}', 'RoleController@permission')->middleware('permission:superAdmin');
- Route::post('role/permission/{role}', 'RoleController@permissionStore')->middleware('permission:superAdmin');
- }
- );
注意:
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 模型删除操作和表外键约束注意事项
站长可不敢删除啊
依赖表数据变化, 本表数据删除
来源: http://www.bubuko.com/infodetail-2880935.html