[] 实现简单的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/** * 简单的 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;}??