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