【捷哥浅谈PHP】第七弹 ---- 基于角色的访问控制RBAC

发布时间:2016-12-7 3:54:08 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"【捷哥浅谈PHP】第七弹 ---- 基于角色的访问控制RBAC",主要涉及到【捷哥浅谈PHP】第七弹 ---- 基于角色的访问控制RBAC方面的内容,对于【捷哥浅谈PHP】第七弹 ---- 基于角色的访问控制RBAC感兴趣的同学可以参考一下。

上文给大家讲解了使用循环输出九九乘法表,逻辑上还是相对简单一些,重在给大家提供一种看程序,解析代码的方法和思路,有什么意见或者建议可以跟帖批斗....好了,不多说了,本文来给大家介绍一下“基于角色的访问控制 ”,说到权限,大家就很头疼,怎么样能灵活把控好一个用户的权限,有些同学会在用户表中加字段或者是在角色表中加相应的权限字段,这样会有一个问题,做起权限来会感觉特别的蹩脚,而且很不灵活,每增加一种权限就要在数据库中增加一个字段,很不利于项目的迭代开发那么我们就需要一种非常灵活的设计模式RBAC,即基于角色的访问控制;我来给大家说下这种设计思想:首先,我们的需求是判断某一个用户对当前操作的控制器或控制器的方法是否有权限访问,如果多个用户同时拥有同样的权限,那我们就需要给这些用户指定同一个用户角色,然后只需要通过角色来对操作的访问进行权限控制,那我们表结构需要这样来设计,这个很重要,如下:第一张数据表(用户表): 字段名称 字段说明 id 用户ID(主键自增) username 用户名 password 用户密码 第二张数据表(角色表): 字段名称 字段说明 id 用户角色ID(主键自增) name 用户角色名称 第三张数据表(节点表): 字段名称 字段说明 id 操作节点ID(主键自增) name 操作节点的名称 zh_name 节点的中文说明 我们使用第三范式来设计关联表,这样做的好处是,避免数据冗余,并且对于一对多,多对一的关系都可以清晰的记录,条理清晰第四张数据表(节点对应角色表): 字段名称 字段说明 role_id 用户角色ID(外键,关联角色表中的主键ID) note_id 操作节点ID(外键,关联节点表中的主键ID) 第五张数据表(用户对应角色表): 字段名称 字段说明 role_id 用户角色ID(外键,关联角色表中的主键ID) user_id 用户ID(外键,关联用户表中的主键ID) 通过这五张表就可以对权限进行访问控制,它的具体操作步骤如下:用户输入用户名密码登录,通过用户表判断,如果输入的用户名密码不合法,跳回重新登录如果合法,在用户表中返回用户的ID号,通过此用户ID号,到用户与角色的关联表中查询出用户的角色ID号,拿到角色ID号,通过此ID号到角色与节点的关联表中查询出此角色拥有的节点访问权限,将此权限节点全部存入SESSION中,当用户访问某一个模块的时候,例如:http://www.lampbroher.net/index.php/stu/index我们用session中的权限与$_GET['m']与$_GET['a']去对比,如果$_GET['m']或者$_GET['a']在SESSION中不存在,说明该用户没有此权限,作出处理即可。参考代码:RBAC类文件: <?php /*+---------------------------------------------------------------------------------------+ | RBAC权限控制类 +-----------------------------------------------------------------------------------------+ | 版权所有 lamp兄弟连 +-----------------------------------------------------------------------------------------+ | 作者: 李捷 ([email protected]) | 最后修改时间: 2012-05-06 18:30 +-----------------------------------------------------------------------------------------+ */ class Rbac{ private $node_tablename; //定义私有属性节点表名称 private $group_auth_tablename; //定义私有属性组权限表名称 private $group_tablename; //定义私有属性用户组表名称 private $group_user_tablename; //定义私有属性用户归属组表名称 private $user_tablename; //定义私有属性用户表名称 /* 构造方法 @param1 string 节点表名称 @param2 string 用户权限表名称 @param3 string 用户组表名称 @param4 string 用户归属组表名称 @param5 string 用户表名称 */ public function __construct($node_tablename='node',$group_auth_tablename='group_auth',$group_tablename='group',$group_user_tablename='group_member',$user_tablename='member'){ $this->node_tablename = $node_tablename; //获取节点表名称 $this->group_auth_tablename = $group_auth_tablename; //获取用户权限表名称 $this->group_tablename = $group_tablename; //获取用户组表名称 $this->group_user_tablename = $group_user_tablename; //获取用户归属组表名称 $this->user_tablename = $user_tablename; //获取用户表名称 } /* 设置节点方法 @param1 string 节点名称 @param2 string 节点父ID @param2 string 节点中文说明 @return int 插入节点记录成功以后的ID */ public function set_node($name,$pid,$zh_name=''){ if(!empty($name) && !empty($pid)){ $node = D($this->node_tablename)->insert(array("name"=>$name,"pid"=>$pid,"zh_name"=>$zh_name)); } return $node; } /* 设置权限方法 @param1 int 组ID @param2 int 节点ID @return int 插入权限记录成功以后的ID */ public function set_auth($gid,$nid){ if(!empty($gid) && !empty($nid)){ $auth = D($this->group_auth_tablename)->insert(array("gid"=>$gid,"nid"=>$nid)); } return $auth; } /* 获取节点方法 @param1 int 节点ID @return array 获取到节点表的相关信息 */ public function get_node($id){ if(!empty($id)){ $data = D($this->node_tablename)->field("id,name,pid")->where(array('id'=>$id))->find(); return $data; }else{ return false; } } /* 获取组权限方法 @param1 int 用户组ID @return array 获取到组权限表的相关信息 */ public function get_auth($gid){ if(!empty($gid)){ $data = D($this->group_auth_tablename)->field("nid")->where(array('gid'=>$gid))->select(); return $data; }else{ return false; } } /* 获取用户组方法 @param1 int 用户ID @return array 获取该用户所对应的用户组id */ public function get_group($uid){ if(!empty($uid)){ $data = D($this->group_user_tablename)->field("gid")->where(array('uid'=>$uid))->select(); return $data; }else{ return false; } } /* 获取节点的子节点方法 @param1 int 节点ID @return array 获取该节点所对应的全部子节点 */ public function get_cnode($nid){ if(!empty($nid)){ $cnode = D($this->node_tablename)->field("name")->where(array('pid'=>$nid))->select(); return $cnode; }else{ return false; } } /* 获取权限方法 @param1 int 用户ID @return array 得到权限列表 */ public function get_access($uid){ if(!empty($uid)){ //调用获取组信息方法 $group = $this->get_group($uid); //遍历组信息 foreach($group as $v){ //将组ID传入获取权限的方法 $auth = $this->get_auth($v['gid']); //获取该组的权限 } //遍历该组的权限数组 foreach($auth as $val){ //将节点的ID传入获取节点信息方法 $node[] = $this->get_node($val['nid']); //获取节点的相关信息 } //遍历节点数组,并拼装 foreach($node as $nval){ if($nval['pid']==0){ $fnode[] = $nval; //将控制器压入fnode数组 //$cnode = $this->get_cnode($nval['id']); }else{ $cnode[] = $nval; //将控制器的方法压入cnode数组 } } //将控制器数组和控制器数组拼装成一个数组 foreach($fnode as $fval){ foreach($cnode as $cval){ if($cval['pid'] == $fval['id']){ $access[$fval['name']][] = $cval['name']; } } } //返回权限列表数组 return $access; }else{ return false; } } /* 检测权限方法 @param1 int 用户ID @return boolean 权限禁止与否 */ public function check($uid){ if(!empty($uid)){ //将权限存入到$_SESSION['Access_List']中 $_SESSION['Access_List'] = $this->get_access($uid); if(!empty($_GET['m'])){ //判断此控制器是否被允许 if(array_key_exists($_GET['m'],$_SESSION['Access_List'])){ //判断此控制器的方法是否被允许 if(in_array($_GET['a'],$_SESSION['Access_List'][$_GET['m']])){ //允许的话返回真 return true; }else{ //否则返回假 return false; } }else{ return false; } }else{ return false; } }else{ //$_SESSION['user_'.$uid]['Access_List'] = 0; return false; } } public function show_node(){ $path = APP_PATH.'/controls/'; $handle = opendir($path); while(false!==($data = readdir($handle))){ if(is_file($path.$data) && $data!='common.class.php' && $data!='pub.class.php'){ $controller = str_replace(".class.php",'',$data); $res = fopen($path.$data,'r'); $str = fread($res,filesize($path.$data)); $pattern = '/function(.*)\(\)/iU'; preg_match_all($pattern, $str, $matches); foreach($matches[1] as $v){ $v = trim($v); $arr[$controller][] = $v; } } } closedir($handle); return $arr; } } 初始化类: <?php /*+---------------------------------------------------------------------------------------+ | 初始化控制器 +-----------------------------------------------------------------------------------------+ | 版权所有 lamp兄弟连 +-----------------------------------------------------------------------------------------+ | 作者: 李捷 ([email protected]) | 最后修改时间: 2012-05-06 18:30 +-----------------------------------------------------------------------------------------+ */ class Common extends Action { /* 初始化方法 */ public function init(){ //如果SESSION为空,则跳转 if(empty($_SESSION['user_login'])){ $this->redirect("pub/index"); } $a = new rbac(); if(!$a->check($_SESSION['user_info']['id'])){ echo "<script>alert('您没有此权限!')</script>"; exit("<script>document.write('<span style=\'font-size:40px;font-weight:bold\'>Access Forbidden');alert('您没有此权限!');</script>"); $this->redirect("pub/index"); } } } 这里给大家写了一个简单的RBAC类,仅供大家学习参考此思想,如有问题可以跟帖回复....欢迎拍砖哈......更多给力文章,请挪步:【捷哥浅谈PHP】第一弹---php位运算符”|”和逻辑运算符”||”遇到的问题 【捷哥浅谈PHP】第二弹---经典算法的运用(冒泡排序和快速排序) 【捷哥浅谈PHP】第三弹---使用二分查找法查找数组中的元素位置 【捷哥浅谈PHP】第四弹---递归函数 【捷哥浅谈PHP】第五弹 --- 分页之九阳神功 【捷哥浅谈PHP】第六弹 ---- 使用for循环输出九九乘法表 原文地址:http://bbs.lampbrother.net/read-htm-tid-118412.html 管理员在2009年8月13日编辑了该文章文章。 --> --> 阅读(67) | 评论(0) | 转发(0) | 0 上一篇:第一个项目快开始了,本人把PHP基础的应用总结了一部分,有需要的同学可以看看 下一篇:【捷哥浅谈PHP】第七弹 ---- 基于角色的访问控制RBAC 相关热门文章 IP Sec VPN与NAT破镜重圆 网站导航 GoAgent图文设置教程 UT2.0正式版下载 tomcat6.0配置(含配置视频下载... 大家都是用什么来管理hadoop集... 网站被人挂了吗,添加了些程序... Nginx如何保证不走宕机的那个... 大家谈谈MYSQL客户端和服务器... 以下代码运行后为何会输出5?... 热门推荐 --> 给主人留下些什么吧!~~ 评论热议

上一篇:初次北上,相遇北京
下一篇:【捷哥浅谈PHP】第七弹 ---- 基于角色的访问控制RBAC

相关文章

相关评论