thinkphp5 权限控制 Hook

  • Post author:
  • Post category:php


* 项目地址:


https://gitee.com/wukongcrm/72crm

* 数据库结构:

** 权限规则表

CREATE TABLE `5kcrm_admin_rule` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `types` tinyint(2) NOT NULL DEFAULT '0' COMMENT '0系统设置1工作台2客户管理3项目管理4人力资源5财务管理6商业智能',
  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '名称',
  `name` varchar(100) NOT NULL DEFAULT '' COMMENT '定义',
  `level` tinyint(5) NOT NULL DEFAULT '0' COMMENT '级别。1模块,2控制器,3操作',
  `pid` int(11) DEFAULT '0' COMMENT '父id,默认0',
  `status` tinyint(3) DEFAULT '1' COMMENT '状态,1启用,0禁用',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=97 DEFAULT CHARSET=utf8 COMMENT='权限规则表';

INSERT INTO `zkt_crm`.`5kcrm_admin_rule` (`id`, `types`, `title`, `name`, `level`, `pid`, `status`) VALUES (‘1’, ‘2’, ‘全部’, ‘crm’, ‘1’, ‘0’, ‘1’);

id          type   title                          name             level        pid      status

根据模块名(level=1),控制器名(level=2),方法名(level=3)

用户组表:

CREATE TABLE `5kcrm_admin_group` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `pid` tinyint(4) NOT NULL COMMENT '分类1管理角色2客户管理角色3人事角色4财务角色5项目角色0自定义角色',
  `title` varchar(100) NOT NULL COMMENT '名称',
  `rules` varchar(2000) NOT NULL DEFAULT '' COMMENT '规则',
  `remark` varchar(100) NOT NULL DEFAULT '' COMMENT '备注',
  `status` tinyint(3) DEFAULT '1' COMMENT '1启用0禁用',
  `type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1本人,2本人及下属,3本部门,4本部门及下属部门,5全部 ',
  `types` tinyint(4) NOT NULL DEFAULT '0' COMMENT '1超级管理员2系统设置管理员3部门与员工管理员4审批流管理员5工作台管理员6客户管理员7项目管理员8公告管理员',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8 COMMENT='角色表';

group表的rules字段关联rule表的自增id

用户所属组:

CREATE TABLE `5kcrm_admin_access` (
  `user_id` int(11) NOT NULL,
  `group_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf

user_id                            group_id

通过group的自增id 就是 access表group_id,查到对应的user_id 就是 用户表的id

对于部门表structure 有 id, name, pid字段

id关联用户表的 structure_id

主要的代码:

application/admin/model/User.php

    /**
     * [getUserByPer 获取权限范围的user_id]
     * @param string $m
     * @param string $c
     * @param string $a
     * @return array|bool
     */
    public function getUserByPer($m = 'index', $c = 'index', $a = 'index'){
        $request = Request::instance();
        $header = $request->header();
        $authKey = $header['authkey'];

        $m = $m ? strtolower($m) : strtolower($request->module());
        $c = $c ? strtolower($c) : strtolower($request->controller());
        $a = $a ? strtolower($a) : strtolower($request->action());

        $cache = cache('Auth_'.$authKey);
        if (!$cache) {
            return false;
        }
        $userInfo = $cache['userInfo'];
        //用户所属用户组类别(数组)
        $groupTypes = $this->getGroupTypeByAction($userInfo['id'], $m, $c, $a);
        //数组去重
        $groupTypes = $groupTypes ? array_unique($groupTypes) : [];
        //用户组类别(1本人,2本人及下属,3本部门,4本部门及下属部门,5全部)
        $adminIds = $this->getAdminId();
        $userIds = [];
        if (in_array($userInfo['id'],$adminIds)) {
            $userIds = getSubUserId(true, 1);
        } else {
            if (!$groupTypes) {
                return [];
            }
            if (in_array(5, $groupTypes)) {
                $userIds = getSubUserId(true, 1);
            } else {
                foreach ($groupTypes as $v) {
                    if ($v == 1) {
                        $userIds = [$userInfo['id']];
                    } elseif ($v == 2) {
                        $userIds = getSubUserId();
                    } elseif ($v == 3) {
                        $userIds = $this->getSubUserByStr($userInfo['structure_id']);
                    } elseif ($v == 4) {
                        $userIds = $this->getSubUserByStr($userInfo['structure_id'], 2);
                    }
                }
            }
        }
        return $userIds ? : [];
    }

获取下属的id:

application/common.php

/**
 * 获取下属userId
 * @author Michael_xu
 * @param $self == true  包含自己
 * @param $type == 0  下属userid
 * @param $type == 1  全部userid
 */
function getSubUserId($self = true, $type = 0)
{   
    $request = Request::instance();
    $header = $request->header();    
    $authKey = $header['authkey'];
    $cache = cache('Auth_'.$authKey);
    if (!$cache) {
        return false;
    }
    $userInfo = $cache['userInfo'];

    $adminTypes = adminGroupTypes($userInfo['id']);  
    if (in_array(1,$adminTypes)) {
        $type = 1;
    }    

    $belowIds = [];
    if (empty($type)) {
        $belowIds = getSubUser($userInfo['id']);
    } else {
        $belowIds = getSubUser(0);
    }   
    if ($self == true) {
        $belowIds[] = $userInfo['id'];
    } else {
        $belowIds = $belowIds ? array_diff($belowIds,array($userInfo['id'])) : [];
    }
    return array_unique($belowIds);
}

/**
 * 获取下属userId
 * @author Michael_xu
 */
function getSubUser($userId)
{
    $sub_user = db('admin_user')
        ->where('parent_id', '=', $userId)
        ->where('status', '<>', 2)
        ->column('id');
    if ($sub_user) {
        foreach ($sub_user as $v) {
            $son_user = getSubUser($v);
            if (!empty($son_user)) {
                $sub_user = array_merge($sub_user, $son_user);
            }
        }
    }
    return $sub_user;
}

application/bi/common.php

<?php
//权限控制
\think\Hook::add('check_auth','app\\common\\behavior\\AuthenticateBehavior');

application/common/behavior/AuthenticateBehavior.php

<?php
// +---------------------------------------------------------------------+
// | Description: WEB端权限判断                                           |
// +---------------------------------------------------------------------+
namespace app\common\behavior;

use think\Request;

class AuthenticateBehavior
{
	public function run(&$params)
	{
        /*防止跨域*/      
        header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
        header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, authKey, sessionId");        
        $request = Request::instance();
        $m = strtolower($request->module());
        $c = strtolower($request->controller());
        $a = strtolower($request->action());        
        //提交方式拦截
        $scan = new \com\Scan();
        $response = $scan->webscan_Check();
		
		$allow = $params['allow']; //登录用户可访问
		$permission = $params['permission']; //无限制
		/*获取头部信息*/ 
        $header = $request->header();
        $authKey = $header['authkey'];
		$cache = cache('Auth_'.$authKey);

        $userInfo = $cache['userInfo'];
    	
    	if (in_array($a, $permission)) {
    		return true;
    	}   

    	if (empty($userInfo)) {
			header('Content-Type:application/json; charset=utf-8');
            exit(json_encode(['code'=>101,'error'=>'请先登录']));
    	}
		if ($userInfo['id'] == 1) {
    		return true;
    	}
    	if (in_array($a, $allow)) {
			return true;
    	}
        //管理员角色
        $adminTypes = adminGroupTypes($userInfo['id']);
        if (in_array(1,$adminTypes)) {
            return true;
        }        
        //操作权限
    	$res_per = checkPerByAction($m, $c, $a); 
    	if (!$res_per) {
			header('Content-Type:application/json; charset=utf-8');
            exit(json_encode(['code'=>102,'error'=>'无权操作']));
    	}
	}
}

在控制器中添加方法  _initialize()

    /**
     * 用于判断权限
     * @permission 无限制
     * @allow 登录用户可访问
     * @other 其他根据系统设置
     **/
    public function _initialize() {
        // 权限控制忽略大小写 必须全部转换为小写
        $action = [
            'permission'=>['read', 'index', 'arealist', 'schoollist', 'save', 'update', 'crypt'],
            'allow'=>['arealist']
        ];
        Hook::listen('check_auth',$action);
        $request = Request::instance();
        $a = strtolower($request->action());
        if (!in_array($a, $action['permission'])) {
            parent::_initialize();
        }
    }

action指的是 控制器的方法



版权声明:本文为fareast_mzh原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。