实现简单的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;
}
 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值