http://www.thinkphp.cn/topic/49737.html
另外一个参考网址:http://www.thinkphp.cn/extend/873.html
声明:本人菜鸟一只,仅以此文献给有和我同样需求的TPer,向高手及前辈致敬!
----------------------------------------------------------------------------
需求说明:我在一个实际项目中需要做到,不同的角色的用户登录以后显示不同的菜单(左侧),以及对应不同的crud权限。
-----------------------------------------------------------------------------
ghzz789大神, 在“Auth权限认证暴力来袭,有图有码有种子,绝对暴力!”(链接地址:http://www.thinkphp.cn/code/714.html)点击下载:https://download.csdn.net/download/jshyzx1999/12284171很好地说明了基于auth的认证类,我下载了他的demo,仔细看过了代码,权限分配的确很清晰,不过好像做到过滤菜单(比方说用户张三仅仅具备A、B菜单的权限A、B、C三个菜单仍旧会显示给他,从某种程度上影响了用户体验。)
---------------------------------------------------------------
白俊遥大神 ,在其博客中也很好的阐述了 基于Auth的权限认证及菜单的分配,我仔细看过其代码以后发现它需要额外的做一个菜单分配的操作。
-----------------------------------------------------------------
luofei614 大神,在“比RBAC更好的权限认证方式(Auth类认证)”(链接地址:http://www.thinkphp.cn/topic/4029.html)一文中同样阐释了基于auth的权限分配,遗憾的是没有提到如何基于权限显示不同的菜单。
-----------------------------------------------------
受到上述大神的启发,稍微改造了一下 auth类,基本实现了我需要的功能。代码如下:
1. 用到的类,TP自带的auth.class.php
2.按照auth.class.php自带的注释,建立必须的数据库:
-- ----------------------------
-- think_auth_rule,规则表,
-- id:主键,name:规则唯一标识, title:规则中文名称 status 状态:为1正常,为0禁用,condition:规则表达式,为空表示存在就验证,不为空表示按照条件验证
-- ----------------------------
DROP TABLE IF EXISTS `think_auth_rule`;
CREATE TABLE `think_auth_rule` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` char(80) NOT NULL DEFAULT '',
`title` char(20) NOT NULL DEFAULT '',
`type` tinyint(1) NOT NULL DEFAULT '1',
`status` tinyint(1) NOT NULL DEFAULT '1',
`condition` char(100) NOT NULL DEFAULT '', # 规则附件条件,满足附加条件的规则,才认为是有效的规则
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- think_auth_group 用户组表,
-- id:主键, title:用户组中文名称, rules:用户组拥有的规则id, 多个规则","隔开,status 状态:为1正常,为0禁用
-- ----------------------------
DROP TABLE IF EXISTS `think_auth_group`;
CREATE TABLE `think_auth_group` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`title` char(100) NOT NULL DEFAULT '',
`status` tinyint(1) NOT NULL DEFAULT '1',
`rules` char(80) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- think_auth_group_access 用户组明细表
-- uid:用户id,group_id:用户组id
-- ----------------------------
DROP TABLE IF EXISTS `think_auth_group_access`;
CREATE TABLE `think_auth_group_access` (
`uid` mediumint(8) unsigned NOT NULL,
`group_id` mediumint(8) unsigned NOT NULL,
UNIQUE KEY `uid_group_id` (`uid`,`group_id`),
KEY `uid` (`uid`),
KEY `group_id` (`group_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
3.添加字段:在think_auth_rule 表中添加字段 pid及ismenu ,用于菜单生成、及是否显示。
4.生成菜单及根据不同权限过滤菜单:
//返回所有菜单分类
function unlimitedForLayer ($cate, $name = 'child', $pid = 0) {
$arr = array();
foreach ($cate as $v) {
if ($v['pid'] == $pid) {
$v[$name] = unlimitedForLayer($cate, $name, $v['id']);
$arr[] = $v;
}
}
return $arr;
}
function getAllMenu(){
$model = M('auth_rule'); //从数据库读取菜单
$cate = $model->where('ismenu = 1')->order('id asc')->select(); //读取用作菜单显示的
//var_dump($cate);die;
$menu=unlimitedForLayer($cate);
//var_dump($model->_sql());
//var_dump($menu);die;
return $menu;
}
function getMenuList($auth_id){
//根据角色权限过滤菜单
$menu_list = getAllMenu(); //获取所有菜单
//print_r($menu_list);die;
if($auth_id!='1'){ //超级管理员加载所有菜单
$auth = new \Think\Auth();
//$authList = $auth->getGroups($auth_id); //根据用户id获取用户组,返回值为数组
//$role_right = $authList[0]['rules']; //得到有效权限id
//var_dump($role_right);die;
//$role_right = explode(',', $role_right); //形成数组
$authList = $auth->getAuthList($auth_id,1); //获取用户需要验证的所有有效规则列表
$map['name']=array('in',$authList);
$role_right = M('auth_rule')->where($map)->getField('id',true);
foreach($menu_list as $k=>$v){
foreach ($v['child'] as $kk=>$vv){
if(!in_array($vv['id'], $role_right)){ //判断数组是否在菜单表里面
unset($menu_list[$k]['child'][$kk]);//过滤菜单
}
}
}
}
return $menu_list;
}
5.基于节点的权限分配。
//_initialize自动运行方法,在每个方法前,系统会首先运动这个方法
public function _initialize()
{
$ctl = CONTROLLER_NAME;
$act = ACTION_NAME;
$auth_id = session('auth_id'); //接受session
if($auth_id==null){
//$this->redirect("/Home/index");
$this->error('请先登录以后再操作!',U('/Home/index'));
}
//无需验证的操作
$uneed_check = array('login','logout','vertifyHandle','vertify','imageUp','upload','login_task');
$uneed_check_cont = array('Index','Main');
if(in_array($ctl,$uneed_check_cont) || $auth_id == '1'){
//后台首页控制器无需验证,超级管理员无需验证
return true;
}elseif(strpos('ajax',$act) || in_array($act,$uneed_check)){
//所有ajax请求不需要验证权限
return true;
}else{
$auth = new \Think\Auth();
if(!$auth->check(MODULE_NAME.'/'.CONTROLLER_NAME.'/'.ACTION_NAME, $auth_id)){
$this->error('没有权限');
}
}
}