首页 后端开发 php教程 浅谈PHP第七弹----基于角色的访问控制RBAC_PHP教程

浅谈PHP第七弹----基于角色的访问控制RBAC_PHP教程

Jul 13, 2016 pm 05:50 PM
http php rbac 基于 控制 角色 访问

上文http://www.BkJia.com/kf/201205/129972.html给大家讲解了使用循环输出九九乘法表,逻辑上还是相对简单一些,重在给大家提供一种看程序,解析代码的方法和思路,有什么意见或者建议可以跟帖批斗....

好了,不多说了,本文来给大家介绍一下“基于角色的访问控制 ”,

说到权限,大家就很头疼,怎么样能灵活把控好一个用户的权限,

有些同学会在用户表中加字段或者是在角色表中加相应的权限字段,

这样会有一个问题,做起权限来会感觉特别的蹩脚,而且很不灵活,每增加一种权限就要在数据库中增加一个字段,很不利于项目的迭代开发

那么我们就需要一种非常灵活的设计模式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类文件:
/*+---------------------------------------------------------------------------------------+
| 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;
}
}
初始化类:
/*+---------------------------------------------------------------------------------------+
| 初始化控制器

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(&#39;您没有此权限!&#39;)</script>";
exit("<script>document.write(&#39;<span style=\&#39;font-size:40px;font-weight:bold\&#39;>Access Forbidden&#39;);alert(&#39;您没有此权限!&#39;);</script>");
$this->redirect("pub/index");
}
}
}

这里给大家写了一个简单的RBAC类,仅供大家学习参考此思想,如有问题可以跟帖回复....

 


作者 zdrjlamp

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/478251.htmlTechArticle上文http://www.2cto.com/kf/201205/129972.html给大家讲解了使用循环输出九九乘法表,逻辑上还是相对简单一些,重在给大家提供一种看程序,解析...
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 带来了多项新功能、安全性改进和性能改进,同时弃用和删除了大量功能。 本指南介绍了如何在 Ubuntu、Debian 或其衍生版本上安装 PHP 8.4 或升级到 PHP 8.4

CakePHP 日期和时间 CakePHP 日期和时间 Sep 10, 2024 pm 05:27 PM

为了在 cakephp4 中处理日期和时间,我们将使用可用的 FrozenTime 类。

讨论 CakePHP 讨论 CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP 是 PHP 的开源框架。它的目的是使应用程序的开发、部署和维护变得更加容易。 CakePHP 基于类似 MVC 的架构,功能强大且易于掌握。模型、视图和控制器 gu

CakePHP 文件上传 CakePHP 文件上传 Sep 10, 2024 pm 05:27 PM

为了进行文件上传,我们将使用表单助手。这是文件上传的示例。

CakePHP 创建验证器 CakePHP 创建验证器 Sep 10, 2024 pm 05:26 PM

可以通过在控制器中添加以下两行来创建验证器。

如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也称为 VS Code,是一个免费的源代码编辑器 - 或集成开发环境 (IDE) - 可用于所有主要操作系统。 VS Code 拥有针对多种编程语言的大量扩展,可以轻松编写

CakePHP 快速指南 CakePHP 快速指南 Sep 10, 2024 pm 05:27 PM

CakePHP 是一个开源MVC 框架。它使开发、部署和维护应用程序变得更加容易。 CakePHP 有许多库可以减少大多数常见任务的过载。

您如何在PHP中解析和处理HTML/XML? 您如何在PHP中解析和处理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示了如何使用PHP有效地处理XML文档。 XML(可扩展的标记语言)是一种用于人类可读性和机器解析的多功能文本标记语言。它通常用于数据存储

See all articles