`

实现简单的ACL

 
阅读更多

终于写完了 呵呵 简单的一个实现

-- ACL Tables

-- 表的结构 `aclresources`
DROP TABLE IF EXISTS `aclresources`;
CREATE TABLE IF NOT EXISTS `aclresources` (
  `rsid` varchar(64) NOT NULL ,
  `access` int(4) NOT NULL default 0,  
  `desc` varchar(240) NOT NULL default '',
  `created_at` int(10) unsigned NOT NULL default 1,
  `updated_at` int(10) unsigned NOT NULL default 0,
  PRIMARY KEY  (`rsid`)
)DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- 表的结构 `aclroles`
DROP TABLE IF EXISTS `aclroles`;
CREATE TABLE IF NOT EXISTS `aclroles` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `rolename` varchar(32) NOT NULL ,
  `durces_aclroles` (
  `rsid` varchar(64) NOT NULL ,
  `role_id` int(10) unsigned NOT NULL ,
  PRIMARY KEY  (`rsid`,`role_id`)
)DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- 表的结构 `ref_users_aclroles`
DROP TABLE IF EXISTS `ref_users_aclroles`;
CREATE TABLE IF NOT EXISTS `ref_users_aclroles` (
  `user_id` int(10) unsigned NOT NULL auto_increment,
  `role_id` int(10) unsigned NOT NULL ,
  PRIMARY KEY  (`user_id`,`role_id`)
)DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- 表的结构 `users`
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `email` varchar(128) NOT NULL,
  `password` varchar(64) NOT NULL,
  `nickname` varchar(32) NOT NULL default '',
  `roles` varchar(240) NOT NULL default '',
  `created_at` int(10) unsigned NOT NULL default 1,
  `updated_at` int(10) unsigned NOT NULL default 0,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `user_email` (`email`)
)DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

 

php 类

<?php
/**
 * 简单的 ACL 权限控制功能
 * 
 * 表定义
 * 
 * 1. 资源定义 	  (rsid,access,desc,created_at,updated_at)
 * 2. 角色定义 	  (id,rolename,desc,created_at,updated_at)
 * 3. 资源-角色关联 (rsid,role_id)
 * 4. 用户-角色关联 (user_id,role_id)
 * 
 * 依赖db.php sqlobject.php
 * 
 * @author vb2005xu.iteye.com 
 */
class AclBase {

	// --- ACL 访问授权
	
	/**
	 * 不允许任何人访问
	 */
	const NOBODY = 0;
	
	/**
	 * 允许任何人访问
	 */
	const EVERYONE = 1;
	
	/**
	 * 允许 拥有角色的用户访问
	 */
	const HAS_ROLE = 2;
	
	/**
	 * 允许 不带有角色的用户访问
	 */
	const NO_ROLE = 3;

	/**
	 * 在 资源-角色关联 定义的 角色才能访问
	 */
	const ALLOCATE_ROLES = 4;	
	
	// 定义相关的 表名
	public $tbResources = 'aclresources';
	public $tbRoles = 'aclroles';
	public $tbRefResourcesRoles = 'ref_aclresources_aclroles';
	public $tbRefUsersRoles = 'ref_users_aclroles';
	
	/**
	 * 格式化 资源的访问权限并返回
	 * 
	 * @return int
	 */
	static function formatAccessValue($access){
		static $arr = array(self::NOBODY,self::EVERYONE,self::HAS_ROLE,self::NO_ROLE,self::ALLOCATE_ROLES);
		return in_array($access,$arr) ? $access : self::NOBODY;
	}
	
	/**
	 * 创建资源,返回资源记录主键
	 * 
	 * @param string $rsid
	 * @param int $access
	 * @param string $desc
	 * 
	 * @return int
	 */
	function createResource($rsid,$access,$desc){
		if (empty($rsid)) return false;
		
		$resource = array(
			'rsid' => $rsid,
			'access' => self::formatAccessValue($access),
			'desc' => $desc,
			'created_at' => CURRENT_TIMESTAMP
		);
		
		return SingleTableCRUD::insert($this->tbResources,$resource);
	}
	
	/**
	 * 修改资源,返回成功状态
	 * 
	 * @param array $resource
	 * @return int
	 */
	function updateResource(array $resource){		
		if (!isset($resource['rsid'])) return false;
		
		$resource['updated_at'] = CURRENT_TIMESTAMP;
		
		return SingleTableCRUD::update($this->tbResources,$resource,'rsid');
	}
	
	/**
	 * 删除资源
	 * 
	 * @param string $rsid
	 * @return int
	 */
	function deleteResource($rsid){
		if (empty($rsid)) return false;
		return SingleTableCRUD::delete($this->tbResources,array('rsid'=>$rsid));
	}
	
	/**
	 * 创建角色,返回角色记录主键
	 * 
	 * @param string $rolename
	 * @param string $desc
	 * 
	 * @return int
	 */
	function createRole($rolename,$desc){
		if (empty($rolename)) return false;
		
		$role = array(
			'rolename' => $rolename,
			'desc' => $desc,
			'created_at' => CURRENT_TIMESTAMP
		);
		
		return SingleTableCRUD::insert($this->tbRoles,$role);
	}
	
	/**
	 * 修改角色,返回成功状态
	 * 
	 * @param array $role
	 * @return int
	 */
	function updateRole(array $role){		
		if (!isset($role['id'])) return false;
		
		if (isset($role['rolename'])) unset($role['rolename']);
		$role['updated_at'] = CURRENT_TIMESTAMP;
		
		return SingleTableCRUD::update($this->tbRoles,$role,'id');
	}
	
	/**
	 * 删除角色
	 * 
	 * @param int $role_id
	 * @return int
	 */
	function deleteRole($role_id){
		if (empty($role_id)) return false;
		return SingleTableCRUD::delete($this->tbRoles,array('role_id'=>(int) $role_id));
	}
	
	/**
	 * 为资源指定角色,每次均先全部移除表中相关记录再插入
	 * 
	 * @param int $rsid
	 * @param mixed $roleIds
	 * @param boolean $setNull 当角色id不存在时,是否将资源从关联表中清空
	 */
	function allocateRolesForResource($rsid,$roleIds,$setNull=false,$defaultAccess=-1){
		if (empty($rsid)) return false;
		
		$roleIds = normalize($roleIds,',');
		if (empty($roleIds)){
			if ($setNull){
				SingleTableCRUD::delete($this->tbRefResourcesRoles,array('rsid'=>$rsid));
				
				if ($defaultAccess != -1){
					$defaultAccess = self::formatAccessValue($defaultAccess);
					$this->updateResource(array('rsid'=>$rsid,'access'=>$defaultAccess));
				}
				return true; 
			}
			return false;
		}
		
		SingleTableCRUD::delete($this->tbRefResourcesRoles,array('rsid'=>$rsid));
		
		$roleIds = array_unique($roleIds);
		
		foreach ($roleIds as $role_id){
			SingleTableCRUD::insert($this->tbRefResourcesRoles,array('rsid'=>$rsid,'role_id'=>(int)$role_id));
		}
		return true;
	}
	
	function cleanRolesForResource($rsid){
		if (empty($rsid)) return false;
		return SingleTableCRUD::delete($this->tbRefResourcesRoles,array('rsid'=>$rsid));
	}
	
	function cleanResourcesForRole($role_id){
		if (empty($role_id)) return false;
		return SingleTableCRUD::delete($this->tbRefResourcesRoles,array('role_id'=>(int) $role_id));
	}
	
	/**
	 * 为角色分配资源,每次均先全部移除表中相关记录再插入
	 * 
	 * @param int $role_id
	 * @param mixed $rsids
	 * 
	 * @return boolean
	 */
	function allocateResourcesForRole($role_id,$rsids){
		if (empty($role_id)) return false;
		
		$role_id = (int) $role_id;
		$rsids = normalize($rsids,',');
		if (empty($rsids)){
			return false;		
		}
		
		SingleTableCRUD::delete($this->tbRefResourcesRoles,array('role_id'=>$role_id));
		
		$rsids = array_unique($rsids);
		
		foreach ($rsids as $rsid){
			SingleTableCRUD::insert($this->tbRefResourcesRoles,array('rsid'=>$rsid,'role_id'=>$role_id));
		}
		return true;
	}
	
	/**
	 * 为用户指派角色,每次均先全部移除表中相关记录再插入
	 * 
	 * 此处在用户很多的时候可能会有性能问题 ... 后面再想怎么优化
	 * 
	 * @param int $user_id
	 * @param mixed $roleIds
	 * 
	 * @return boolean
	 */
	function allocateRolesForUser($user_id,$roleIds){
		if (empty($user_id)) return false;
		
		$user_id = (int) $user_id;
		$roleIds = normalize($roleIds,',');
		if (empty($roleIds)){
			return false;		
		}
		
		SingleTableCRUD::delete($this->tbRefUsersRoles,array('user_id'=>$user_id));
		
		$roleIds = array_unique($roleIds);
		
		foreach ($roleIds as $roleId){
			SingleTableCRUD::insert($this->tbRefUsersRoles,array('user_id'=>$user_id,'role_id'=>$role_id));
		}
		return true;
	}
	
	/**
	 * 清除用户的角色信息
	 * 
	 * @param int $user_id
	 * 
	 * @return boolean
	 */
	function cleanRolesForUser($user_id){
		if (empty($user_id)) return false;
		return SingleTableCRUD::delete($this->tbRefUsersRoles,array('user_id'=>(int) $user_id));
	}
	
	/**
	 * 清除角色的用户关联
	 * 
	 * @param int $role_id
	 * 
	 * @return boolean
	 */
	function cleanUsersForRole($role_id){
		if (empty($role_id)) return false;
		return SingleTableCRUD::delete($this->tbRefUsersRoles,array('role_id'=>(int) $role_id));
	}
		
}

 

具体 检测的代码 如下:

/**
 * 对资源进行acl校验
 * 
 * @param string $rsid 资源标识
 * @param array $user  特定用户,不指定则校验当前用户
 * 
 * @return boolean
 */
function aclVerity($rsid ,array $user = null){
	
	if (empty($rsid)) return false;

	if (!CoreApp::$defaultAcl) {
		CoreApp::$defaultAcl = new AclFlat();
	}
	
	$rsRow = aclGetResource($rsid);
	
	// 未定义资源的缺省访问策略
	if (!$rsRow) return false;
	
	CoreApp::writeLog($rsRow,'test');
	
	$rsRow['access'] = AclBase::formatAccessValue($rsRow['access']);
	
	// 允许任何人访问
	if (AclBase::EVERYONE == $rsRow['access']) return true;
	
	// 不允许任何人访问
	if (AclBase::NOBODY == $rsRow['access']) return false;
	
	// 获取用户信息
	if (empty($user)) $user = isset($_SESSION['SI-SysUser']) ? $_SESSION['SI-SysUser'] : null;
	
	// 用户未登录,则当成无访问权限
	if (empty($user)) return false;
	
	$user['roles'] = empty($user['roles']) ? null : normalize($user['roles'],';');
	
	$userHasRoles = !empty($user['roles']);
	
	/**
	 * 允许 不带有角色的用户访问
	 */
	if (AclBase::NO_ROLE == $rsRow['access']) return $userHasRoles ? false : true;
	
	/**
	 * 允许 带有角色的用户访问
	 */
	if (AclBase::HAS_ROLE == $rsRow['access']) return $userHasRoles ? true : false;
	
	// --- 对用户进行 资源 <-> 角色 校验
	if ($userHasRoles){
		foreach ($user['roles'] as $role_id){
			if ( aclGetRefResourcesRoles($rsid,$role_id) )
				return true;
		}
		dump($user);
	}
	return false;
}
 

 

 

2
5
分享到:
评论
4 楼 Theobob 2016-05-24  
3 楼 yuanhui001 2011-09-07  
     
2 楼 vb2005xu 2011-09-07  

/**
 * 对资源进行acl校验
 * 
 * @param string $rsid 资源标识
 * @param array $user  特定用户,不指定则校验当前用户
 * 
 * @return boolean
 */
function aclVerity($rsid ,array $user = null){
	
	if (empty($rsid)) return false;

	if (!CoreApp::$defaultAcl) {
		CoreApp::$defaultAcl = new AclFlat();
	}
	
	$rsRow = aclGetResource($rsid);
	
	// 未定义资源的缺省访问策略
	if (!$rsRow) return false;
	
	CoreApp::writeLog($rsRow,'test');
	
	/*
	 * 校验步骤如下:
	 * 
	 * 1. 先校验 资源本身 access 属性
	 * 	  EVERYONE => true,NOBODY  => false * 其它的属性在下面继续校验
	 * 2. 从 session(或者 用户session表)中获取角色id集合
	 * 3. 如果 用户拥有角色 则 HAS_ROLE => true , NO_ROLE => false;反之亦然
	 * 4. 如果资源 access == ALLOCATE_ROLES
	 * 		1. 从缓存(或者 $tbRefResourcesRoles)中获取 资源对应的角色id集合
	 * 		2. 将用户拥有的角色id集合 与 资源对应的角色id集合求交集
	 * 		3. 存在交集 => true;否则 => false
	 */ 
	
	$rsRow['access'] = AclBase::formatAccessValue($rsRow['access']);
	
	// 允许任何人访问
	if (AclBase::EVERYONE == $rsRow['access']) return true;
	
	// 不允许任何人访问
	if (AclBase::NOBODY == $rsRow['access']) return false;
	
	// 获取用户信息
	if (empty($user)) $user = isset($_SESSION['SI-SysUser']) ? $_SESSION['SI-SysUser'] : null;
	
	// 用户未登录,则当成无访问权限
	if (empty($user)) return false;
	
	$user['roles'] = empty($user['roles']) ? null : normalize($user['roles'],';');
	
	$userHasRoles = !empty($user['roles']);
	
	/**
	 * 允许 不带有角色的用户访问
	 */
	if (AclBase::NO_ROLE == $rsRow['access']) return $userHasRoles ? false : true;
	
	/**
	 * 允许 带有角色的用户访问
	 */
	if (AclBase::HAS_ROLE == $rsRow['access']) return $userHasRoles ? true : false;
	
	// --- 对用户进行 资源 <-> 角色 校验
	if ($userHasRoles){
		foreach ($user['roles'] as $role_id){
			if ( aclGetRefResourcesRoles($rsid,$role_id) )
				return true;
		}
		dump($user);
	}
	return false;
}

/**
 * 重新生成 角色资源访问控制表
 * 
 * @param string $actTable ACL表名称
 * @param boolean $return 是否返回重新生成的列表
 * 
 * @return mixed
 */
function aclRebuildACT($actTable ,$return = false){
	if (empty($actTable)) return false;
	
	global $globalConf;
	$rst = null;
	$cacheId = null;
	
	switch($actTable){
		case CoreApp::$defaultAcl->tbResources:
			$cacheId = 'acl-resources';
			$rst = SingleTableCRUD::findAll(CoreApp::$defaultAcl->tbResources);
			// 转成 哈希表结构
			if ($rst){
				$rst = array_to_hashmap($rst,'rsid');
			}
			break;
		case CoreApp::$defaultAcl->tbRoles:
			$cacheId = 'acl-roles';
			$rst = SingleTableCRUD::findAll(CoreApp::$defaultAcl->tbRoles);
			// 转成 哈希表结构
			if ($rst){
				$rst = array_to_hashmap($rst,'id');
			}
			break;
		case CoreApp::$defaultAcl->tbRefResourcesRoles:
			$cacheId = 'acl-roles_has_resources';
			$rst = SingleTableCRUD::findAll(CoreApp::$defaultAcl->tbRefResourcesRoles);
			if ($rst){				
				$_ = array();
				foreach ($rst as $row) {
					$ref_id = "{$row['rsid']}<-|->{$row['role_id']}"; 
					$_[$ref_id] = $row;
		        }
		        unset($rst);
		        $rst = $_;
			}
			break;
	}
	
	if ($cacheId)
		writeCache($globalConf['runtime']['cacheDir'] ,$cacheId ,$rst ,true);
	
	if ($return) return $rst;
}

/**
 * 获取 角色资源访问控制表 数据
 * 
 * @param string $actTable ACL表名称
 * 
 * @return mixed
 */
function aclGetACT($actTable){
	if (empty($actTable)) return false;
	
	static $rst = array();
		
	$cacheId = null;
	
	switch($actTable){
		case CoreApp::$defaultAcl->tbResources:
			$cacheId = 'acl-resources';
			break;
		case CoreApp::$defaultAcl->tbRoles:
			$cacheId = 'acl-roles';
			break;
		case CoreApp::$defaultAcl->tbRefResourcesRoles:
			$cacheId = 'acl-roles_has_resources';
			break;
			
	}
	
	if (!$cacheId) return null;
	
	if (isset($rst[$cacheId])) return $rst[$cacheId];
	
	global $globalConf;	
	// 900
	$rst[$cacheId] = getCache($globalConf['runtime']['cacheDir'],$cacheId,0);
	if ( !$rst[$cacheId] ){
		$rst[$cacheId] = aclRebuildACT($actTable,true);
	}
	
	return $rst[$cacheId];
}

/**
 * 获取 资源 记录
 * 
 * @param string $rsid
 * 
 * @return array
 */
function aclGetResource($rsid){
	static $rst = null;
	if (!$rst){
		$rst = aclGetACT(CoreApp::$defaultAcl->tbResources);
		if (!$rst) $rst = array();
	}
	return isset($rst[$rsid]) ? $rst[$rsid] : null;
}

/**
 * 获取 角色 记录
 * 
 * @param int $role_id
 * 
 * @return array
 */
function aclGetRole($role_id){
	static $rst = null;
	if (!$rst){
		$rst = aclGetACT(CoreApp::$defaultAcl->tbRoles);
		if (!$rst) $rst = array();
	}
	return isset($rst[$role_id]) ? $rst[$role_id] : null;
}

/**
 * 获取 用户角色关联 记录,此方法可以校验资源是否可被此角色调用
 * 
 * @param string $rsid
 * @param int $role_id
 * 
 * @return array
 */
function aclGetRefResourcesRoles($rsid,$role_id){
	static $rst = null;
	if (!$rst){
		$rst = aclGetACT(CoreApp::$defaultAcl->tbRefResourcesRoles);
		if (!$rst) $rst = array();
	}
	$ref_id = "{$rsid}<-|->{$role_id}";
	CoreApp::writeLog(isset($rst[$ref_id])?$rst[$ref_id]:'nodata',$ref_id);
	return isset($rst[$ref_id]) ? $rst[$ref_id] : null;
}

1 楼 vb2005xu 2011-08-05  
http://code.google.com/p/php-excel/downloads/list 迷你好用的 EXCEL xml 输出方案

相关推荐

    荒城原创动态ACL实现简单上网用户授权

    这种情况下,我们一般通过 ACL 来实现。 ACL 是个很好的工具,但是也有它本身的硬伤,就是不够智能。比如 如果说一个网段中有 200 台电脑,其中 30 台是领导的,需要访问互 联网,另外 170 台是员工的,不允许访问...

    acl.zip_ACL_权限控制

    通过GET传递参数,实现简单的acl权限控制

    配置标准ACL

    使用标准IP ACL实现简单的访问控制 标准ip ACL可以根据过滤规则对网络中的数据进行过滤

    php中实现简单的ACL 完结篇

    终于写完了 呵呵 简单的一个实现,学习php的朋友可以参考下。

    cisco路由器的ACL实验

    cisco路由器访问控制列表练习,用PKT做的模拟实验基本实现简单的校园网络的架构

    PHP-ACL:一个简单的,支持Composer的访问控制和用户cookie登录系统

    安装您可以克隆存储库并直接使用文件,但是一切都已针对composer进行了设置,这很简单: composer require gburtini/acl用法使用此程序包分为三个部分。 为您的用例实现身份验证器制定访问控制列表。 集成User类。 ...

    acl-check:一个用 C++ 编写的简单控制台应用程序,用于对网络设备配置中包含的访问控制列表进行完整的静态分析

    AclCheck是一个用 C++ 编写的简单控制台应用程序,用于对网络设备配置中包含的访问控制列表进行完整的静态分析。 工具检测给定配置文件中每个 ACL 规则之间的冲突。 即使对于非常大的 ACL(10000+ 条规则),使用的...

    简单有效的文本匹配:ACL2019论文“具有更丰富的对齐功能的简单有效的文本匹配”的源代码

    这是ACL 2019论文的原始Tensorflow实现。 Pytorch实施: : 。 快速链接 简单有效的文本匹配 RE2是用于通用文本匹配应用程序的快速而强大的神经体系结构。 在文本匹配任务中,模型将两个文本序列作为输入并预测它们...

    简单有效的文本匹配pytorch:ACL2019论文“具有更丰富的对齐功能的简单有效的文本匹配”的pytorch实现

    RE2 这是ACL 2019论文“具有更丰富的对齐功能的简单有效的文本匹配”的pytorch实现。 原始的Tensorflow实现: : 。快速链接简单有效的文本匹配RE2是用于通用文本匹配应用程序的快速而强大的神经体系结构。 在文本...

    综合组网实验(eNSP)(vlan、vlan间通信、nat地址转换、acl、dhcp、ospf……)

    本次实验模拟学校实验室的网络环境,通过虚拟环境进行组网,通过vlan、路由、访问控制等,实现不同实验室之间的通信,并且可以通过ACL控制某一个实验室的网络通信,进行简单的组网分析 二、应用的网络知识 Vlan Vlan...

    路由器与防火墙的区别.docx

    三、核心技术 路由器核心的ACL列表是基于简单的包过滤,属于OSI第三层过滤。从防火墙技术实现的角度来说,防火墙是基于状态包过滤的应用级信息流过滤。 内网的一台服务器,通过路由器对内网提供服务,假设提供服务...

    网络互联与路由实训报告.doc

    为了更深入的了解企业网络,可以实现一些简单的拓扑搭建,掌握以下能力: (1)学习了解基础的网络架构框架及相关基础知识、概念。 (2)熟练掌握静态路由,OSPF等基本路由协议的配置。 (3)学习VLAN的创建,正确划分VLAN...

    ACL:动画压缩库

    虽然可以通过简单的技巧轻松地实现某种程度的压缩,但是要获得很高的压缩率,快速解压缩,同时又不影响最终压缩动画的准确性,则需要格外小心。 目标 该库有四个主要目标: 实现最先进的技术并准备生产动画压缩...

    服务器上下感知.docx

    使用Python-api实现列出节点、创建节点、获取节点数据、修改节点数据、删除节点、获取节点ACL等代码编写 使用python-api实现使用超级用户授权连接,并验证 Zookeeper实现主机上下线感知,linux主机名与ip地址使用...

    CI框架中通过hook的方式实现简单的权限控制

    根据自己的实际情况,需要两个文件,一个是权限控制类,Acl,另外一个是权限配置的文件acl.php放在了config这个目录下。 Acl这个类放在了application/hook/acl.php。通过application/config/config.php文件开启hook...

    基于eNSP的简单企业网络规划与设计

    目 录 摘要 1 1 需求分析 2 1.1 项目背景 2 1.2 项目需求 2 1.3 设计目标 2 2 拓扑结构设计 3 ...4.7 ACL技术 15 4.7.1 技术介绍 15 4.7.2 技术配置 16 5 系统连通性测试 16 6 结论 23 参考文献 24

    网络课程设计报告 了解路由器,交换机,

    更深了解路由器,交换机,PC机之间的配置与应用,熟练掌握一些简单的的网络应用 连接,熟练掌握路由器和交换机的基本配置;掌握DHCP、ACL、VLAN、和NET协议和相应的技术;提高对实际网络问题的分析和解决能力。该...

    小型校园网设计规划.pkt

    Cisco Packet Tracer设计的小型校园网,可用于了解计算机网络的简单工作结果与原理。用一组网络设备模拟构建一个...使用 ACL 访问控制列表为校园网提供防火墙,并通过 NAT 转换实现与外网之间的通信;无线上网功能。

    Cisco最全配置命令

    OSPF基于链路的简单口令认证 32 ospf 注入一条默认路由 33 多区域OSPF 35 多区域OSPF基本配置 36 多区域OSPF手动汇总 38 Ospf 末节区域和完全末节区域 40 Ospf NSSA区域 42 Ospf虚链路 44 不连续区域0的虚连接 46 IS...

Global site tag (gtag.js) - Google Analytics