11 php RBAC

来源:互联网 发布:python可以跨平台吗 编辑:程序博客网 时间:2024/05/17 00:02

首先,我们的需求是判断某一个用户对当前操作的控制器或控制器的方法是否有权限访问,

如果多个用户同时拥有同样的权限,那我们就需要给这些用户指定同一个用户角色,然后只需要通过角色来对操作的访问进行权限控制,

那我们表结构需要这样来设计,这个很重要,如下:

第一张数据表(用户表):
 

字段名称字段说明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权限控制类

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
/*+---------------------------------------------------------------------------------------+
| 初始化控制器

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类,仅供大家学习参考此思想,如有问题可以跟帖回复....

 


作者 zdrjlamp


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 斗鱼直播卡顿怎么办 斗鱼怎么办卡怎么设置 无线网不能用了怎么办 率土之滨流浪后怎么办 率土之滨围洛阳怎么办 率土之滨没资源怎么办 竞彩改期的比赛怎么办 变性人老了会怎么办 冰箱放阳台直晒怎么办 喝了冰牛奶胃痛怎么办 空腹喝咖啡胃疼怎么办 空腹吃柿子胃疼怎么办 mac重启卡住了怎么办 快玩下载速度慢怎么办 微信消息不提示怎么办 车被物业锁了怎么办 去香港办的团签怎么办 香港个人签证g签怎么办 诛仙3挂机掉线怎么办 大神f2开不了机怎么办 昆仑账号忘记了怎么办 三星手机wifi信号弱怎么办 6个月的宝宝缺钙怎么办 半岁宝宝坐不稳怎么办 你宝宝老不睡觉怎么办 三岁宝宝摸咪咪怎么办 宝宝很困又不睡怎么办 两岁宝宝摸咪咪怎么办 失眠怎么办如何快速睡眠小偏方 9岁儿童睡不着觉怎么办 2岁儿童睡不着觉怎么办 多梦头晕没精神怎么办 晚上睡眠不好老做梦怎么办 睡醒后喉咙干痛怎么办 感冒了喉咙干痛怎么办 老公想你了你该怎么办 赌博赢来的100万怎么办 赌博输了60万怎么办 网赌欠债10几万怎么办 网赌欠债还不起怎么办 赌博输了好多钱怎么办