1:创建表结构
创建用户表 user
创建权限表 permission
创建角色表 role
创建用户角色表 user_role
创建角色权限表 role_permission
2:创建中间件权限判断和目录生成
<?php
/**
* 检测后台用户是否登录中间件
* 此中间件可以跟登录验证登录中间分离
*/
namespace App\Http\Middleware;
use App\Components\AdminManager;
use App\Components\Common\ApiResponse;
use App\Components\PermissionManager;
use Closure;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\View;
class CheckAdminLogin
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
//检测session中是否有登录信息
if (!$request->session()->has('self_admin')) {
return redirect('/admin/login');
}
$self_admin = $request->session()->get('self_admin');
$self_admin = AdminManager::getById($self_admin->id); //增加判断status==0的失效踢出管理员
if ($self_admin->status == '0') {
return redirect('/admin/login');
}
//组成redis的key名称
$key = 'banni:admin:menu:'.$self_admin->id;
//自己写的,销毁redis中用户权限的缓存
// PermissionManager::destroyPermissions();
//获取redis中用户权限信息
$admin_menu_data = Redis::get($key);
//判断是否是超级管理员
$is_admin = $self_admin->role === 0?true:false;
//判断是否在redis中获取到该缓存
if( !$admin_menu_data ){
//未获取到缓存重新生成用户权限信息,存储到redis中
if(!PermissionManager::getMenuList($self_admin->id,$is_admin)){
return redirect('/admin/login');
}
$admin_menu_data = Redis::get($key);
}
//获取用户权限信息
$admin_menu_data = unserialize($admin_menu_data);
//获取用户权限
$permissions_arr = $admin_menu_data['permission_auth'];
//追加默认权限到权限数组中
array_push($permissions_arr,'/admin/index','/admin/index/index','/admin/logout','/','/index','/admin/index/error','/admin/overview/index','/admin/overview/orderGMVTrend','/admin/overview/userTrend','/admin/welcome');
//获取请求url,过滤带参数的路由,重新封装
$path_arr = explode('/',$request->path());
if( is_numeric(array_pop($path_arr)) ){
$permission_path = '/'.implode('/',$path_arr);
}else{
$permission_path = '/'.$request->path();
}
//判断不是超级管理员,并且没有此权限
if( !$is_admin && !in_array( $permission_path,$permissions_arr) ){
//判断接收方式返回关联信息
if( $request->ajax() ){
return ApiResponse::makeResponse(false, "", ApiResponse::INNER_ERROR,'权限不足,请联系管理员');
}else{
return redirect('/admin/index/error');
}
}
//传入目录数组到前端,像layui这种只生成一次目录的,可以只请求一次,但是我还没做
view()->share('admin_menu', $admin_menu_data['menu_list']);
//如果不需要判断按钮显示权限的,可以注释此步骤
view()->share('admin_permissions', $permissions_arr);
return $next($request);
}
}
生成用户权限方法
/*
* 生成菜单列表
* $adming_id 关联表id
* $is_admin 是否是超级管理员
* $type 类型:1后台管理;2:公会后台管理
*
*/
public static function getMenuList($adming_id,$is_admin = false,$type = 1){
switch ($type){
case 1:
$f_table = 'admin';
break;
case 2:
$f_table = 'guild_user';
break;
default:
break;
}
//构建菜单列表数组
$menu_list = [];
//构建用户权限列表
$permission_auth = [];
//判断是否是超级管理员
if( $is_admin ){
$con_arr = [
'status' => 1,
'type' => $type
];
$permissions = self::getListByCon($con_arr,false)->toArray();
foreach ($permissions as $permission){
$permission_auth[] = $permission['url'];
if( $permission['is_display'] ){
$menu_list[$permission['f_id']][] = [
"id" => $permission['id'],
"name" => $permission['name'],
"url" => $permission['url'],
"is_display" => $permission['is_display'],
"f_id" =>$permission['f_id'],
"icon" => $permission['icon']
];
}
}
}else{
//非超级管理员获取目录权限
$user_role_where = [
'f_table' => $f_table,
'f_id' => $adming_id,
'status' => 1
];
$user_roles = UserRoleManager::getListByCon($user_role_where,false);
foreach ( $user_roles as $user_role ){
$user_role = UserRoleManager::getInfoByLevel($user_role,'Y,1');
}
//生成目录信息和权限数组
foreach($user_roles as $user_role){
foreach ( $user_role['roles'] as $role) {
foreach( $role['permissions'] as $permission ){
$permission_auth[] = $permission['url'];
if( $permission['is_display'] ){
$menu_list[$permission['f_id']][] = [
"id" => $permission['id'],
"name" => $permission['name'],
"url" => $permission['url'],
"is_display" => $permission['is_display'],
"f_id" =>$permission['f_id'],
"icon" => $permission['icon'],
"seq" => $permission['seq']
];
}
}
}
}
//冒泡排序目录
foreach ( $menu_list as $key => $menu ){
self::bubbleSort($menu_list[$key]);
}
}
//构建redis中的key
$type_key = $type==1?'admin':'guild:admin';
$menu_list_key = 'banni:'.$type_key . ':menu:'.$adming_id;
$admin_menu_list = [
'admin_id'=> $adming_id,
'menu_list'=> $menu_list,
'permission_auth' => $permission_auth
];
//删除有序集合中用户的权限
Redis::del($menu_list_key);
//插入权限进redis有序集合中,分数为用id
if( Redis::set($menu_list_key, serialize($admin_menu_list) ) ){
return true;
}else{
return false;
}
}
/*
* 销毁所有权限相关缓存文件
*/
public static function destroyPermissions($type=1){
switch ($type){
case 1:
$prefix = 'banni:admin:menu:*';
break;
case 2:
$prefix = 'banni:guild:admin:menu:*';
break;
}
$keys = Redis::keys($prefix);
foreach( $keys as $key ){
Redis::del($key);
}
// Redis::del($key);
}
/*
* 冒泡排序菜单顺序
*/
public static function bubbleSort(&$data){
for ($i = 0; $i < count($data) ; $i++) {
for ($j = $i+1; $j < count($data); $j++) {
if ($data[$i]['seq'] < $data[$j]['seq']) {
$tem = $data[$i]; // 这里临时变量,存贮$i的值
$data[$i] = $data[$j]; // 第一次更换位置
$data[$j] = $tem; // 完成位置互换
}
}
}
}
3:前端目录生成
<!-- 循环一级目录 -->
@foreach( $admin_menu[0] as $key=>$value)
<li data-name="app" class="layui-nav-item">
<!-- 判断一级目录是否可跳转,可跳转目录没有子集 -->
@if( $value['url'] )
<a href="javascript:;" lay-href="{{ asset($value['url'], true) }}?not_in_admin_id=0" lay-tips="{{$value['name']}}"
lay-direction="2">
<i class="layui-icon {{$value['icon']}}"></i>
<cite>{{$value['name']}}</cite>
</a>
@else
<a href="javascript:;" lay-tips="{{$value['name']}}" lay-direction="2">
<i class="layui-icon {{$value['icon']}}"></i>
<cite>{{$value['name']}}</cite>
</a>
<dl class="layui-nav-child">
<!-- 判断是否有子集 -->
@if (isset($admin_menu[$value['id']]))
<!-- 循环子集生成菜单 -->
@foreach($admin_menu[$value['id']] as $val)
<!-- 判断是否有子集,这是第三层,如果没有三层菜单,判断可以不要 -->
@if( isset( $admin_menu[$val['id']] ) )
<dd data-name="setting">
<a href="javascript:;">{{$val["name"]}}</a>
<dl class="layui-nav-child">
@foreach($admin_menu[$val['id']] as $v)
<dd data-name="workorder">
<a lay-href="{{ asset( $v['url'] , true) }}" >{{$v["name"]}}</a>
</dd>
@endforeach
</dl>
</dd>
@else
<dd data-name="workorder">
<a lay-href="{{ asset( $val['url'] , true) }}" >{{$val["name"]}}</a>
</dd>
@endif
@endforeach
@endif
</dl>
@endif
</li>
@endforeach
如果有按钮需要是否显示判断
<!-- 判断此链接是否在权限中,如果在就显示,不在就隐藏 -->
@if( $data->audit_status == 0 && in_array('/admin/guildGameSettledApply/approve',$admin_permissions) )
<button class="layui-btn layui-btn-sm" lay-submit="" onclick="approve(this,'{{$data->id}}','{{asset('/admin/guildGameSettledApply/approve', true)}}')">
审核通过
</button>
@endif