laravel 中间件做权限目录管理

1:创建表结构

创建用户表 user

创建权限表 permission

image.png

创建角色表 role

创建用户角色表 user_role

image.png

创建角色权限表  role_permission

image.png

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                                                                                                                         
                                        

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章