php中实现简单的ACL完结篇
PHP 实现 简单 ACL 完结篇
2023-06-13 09:14:30 时间
--ACLTables
--表的结构`aclresources`
DROPTABLEIFEXISTS`aclresources`;
CREATETABLEIFNOTEXISTS`aclresources`(
`rsid`varchar(64)NOTNULL,
`access`int(4)NOTNULLdefault0,
`desc`varchar(240)NOTNULLdefault"",
`created_at`int(10)unsignedNOTNULLdefault1,
`updated_at`int(10)unsignedNOTNULLdefault0,
PRIMARYKEY(`rsid`)
)DEFAULTCHARSET=utf8COLLATE=utf8_unicode_ci;
--表的结构`aclroles`
DROPTABLEIFEXISTS`aclroles`;
CREATETABLEIFNOTEXISTS`aclroles`(
`id`int(10)unsignedNOTNULLauto_increment,
`rolename`varchar(32)NOTNULL,
`desc`varchar(240)NOTNULLdefault"",
`created_at`int(10)unsignedNOTNULLdefault1,
`updated_at`int(10)unsignedNOTNULLdefault0,
PRIMARYKEY(`id`),
UNIQUEKEY`rolename`(`rolename`)
)DEFAULTCHARSET=utf8COLLATE=utf8_unicode_ci;
--表的结构`ref_aclresources_aclroles`
DROPTABLEIFEXISTS`ref_aclresources_aclroles`;
CREATETABLEIFNOTEXISTS`ref_aclresources_aclroles`(
`rsid`varchar(64)NOTNULL,
`role_id`int(10)unsignedNOTNULL,
PRIMARYKEY(`rsid`,`role_id`)
)DEFAULTCHARSET=utf8COLLATE=utf8_unicode_ci;
--表的结构`ref_users_aclroles`
DROPTABLEIFEXISTS`ref_users_aclroles`;
CREATETABLEIFNOTEXISTS`ref_users_aclroles`(
`user_id`int(10)unsignedNOTNULLauto_increment,
`role_id`int(10)unsignedNOTNULL,
PRIMARYKEY(`user_id`,`role_id`)
)DEFAULTCHARSET=utf8COLLATE=utf8_unicode_ci;
--表的结构`users`
DROPTABLEIFEXISTS`users`;
CREATETABLE`users`(
`id`int(10)unsignedNOTNULLauto_increment,
`email`varchar(128)NOTNULL,
`password`varchar(64)NOTNULL,
`nickname`varchar(32)NOTNULLdefault"",
`roles`varchar(240)NOTNULLdefault"",
`created_at`int(10)unsignedNOTNULLdefault1,
`updated_at`int(10)unsignedNOTNULLdefault0,
PRIMARYKEY(`id`),
UNIQUEKEY`user_email`(`email`)
)DEFAULTCHARSET=utf8COLLATE=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.phpsqlobject.php
*
*@authorvb2005xu.iteye.com
*/
classAclBase{
//---ACL访问授权
/**
*不允许任何人访问
*/
constNOBODY=0;
/**
*允许任何人访问
*/
constEVERYONE=1;
/**
*允许拥有角色的用户访问
*/
constHAS_ROLE=2;
/**
*允许不带有角色的用户访问
*/
constNO_ROLE=3;
/**
*在资源-角色关联定义的角色才能访问
*/
constALLOCATE_ROLES=4;
//定义相关的表名
public$tbResources="aclresources";
public$tbRoles="aclroles";
public$tbRefResourcesRoles="ref_aclresources_aclroles";
public$tbRefUsersRoles="ref_users_aclroles";
/**
*格式化资源的访问权限并返回
*
*@returnint
*/
staticfunctionformatAccessValue($access){
static$arr=array(self::NOBODY,self::EVERYONE,self::HAS_ROLE,self::NO_ROLE,self::ALLOCATE_ROLES);
returnin_array($access,$arr)?$access:self::NOBODY;
}
/**
*创建资源,返回资源记录主键
*
*@paramstring$rsid
*@paramint$access
*@paramstring$desc
*
*@returnint
*/
functioncreateResource($rsid,$access,$desc){
if(empty($rsid))returnfalse;
$resource=array(
"rsid"=>$rsid,
"access"=>self::formatAccessValue($access),
"desc"=>$desc,
"created_at"=>CURRENT_TIMESTAMP
);
returnSingleTableCRUD::insert($this->tbResources,$resource);
}
/**
*修改资源,返回成功状态
*
*@paramarray$resource
*@returnint
*/
functionupdateResource(array$resource){
if(!isset($resource["rsid"]))returnfalse;
$resource["updated_at"]=CURRENT_TIMESTAMP;
returnSingleTableCRUD::update($this->tbResources,$resource,"rsid");
}
/**
*删除资源
*
*@paramstring$rsid
*@returnint
*/
functiondeleteResource($rsid){
if(empty($rsid))returnfalse;
returnSingleTableCRUD::delete($this->tbResources,array("rsid"=>$rsid));
}
/**
*创建角色,返回角色记录主键
*
*@paramstring$rolename
*@paramstring$desc
*
*@returnint
*/
functioncreateRole($rolename,$desc){
if(empty($rolename))returnfalse;
$role=array(
"rolename"=>$rolename,
"desc"=>$desc,
"created_at"=>CURRENT_TIMESTAMP
);
returnSingleTableCRUD::insert($this->tbRoles,$role);
}
/**
*修改角色,返回成功状态
*
*@paramarray$role
*@returnint
*/
functionupdateRole(array$role){
if(!isset($role["id"]))returnfalse;
if(isset($role["rolename"]))unset($role["rolename"]);
$role["updated_at"]=CURRENT_TIMESTAMP;
returnSingleTableCRUD::update($this->tbRoles,$role,"id");
}
/**
*删除角色
*
*@paramint$role_id
*@returnint
*/
functiondeleteRole($role_id){
if(empty($role_id))returnfalse;
returnSingleTableCRUD::delete($this->tbRoles,array("role_id"=>(int)$role_id));
}
/**
*为资源指定角色,每次均先全部移除表中相关记录再插入
*
*@paramint$rsid
*@parammixed$roleIds
*@paramboolean$setNull当角色id不存在时,是否将资源从关联表中清空
*/
functionallocateRolesForResource($rsid,$roleIds,$setNull=false,$defaultAccess=-1){
if(empty($rsid))returnfalse;
$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));
}
returntrue;
}
returnfalse;
}
SingleTableCRUD::delete($this->tbRefResourcesRoles,array("rsid"=>$rsid));
$roleIds=array_unique($roleIds);
foreach($roleIdsas$role_id){
SingleTableCRUD::insert($this->tbRefResourcesRoles,array("rsid"=>$rsid,"role_id"=>(int)$role_id));
}
returntrue;
}
functioncleanRolesForResource($rsid){
if(empty($rsid))returnfalse;
returnSingleTableCRUD::delete($this->tbRefResourcesRoles,array("rsid"=>$rsid));
}
functioncleanResourcesForRole($role_id){
if(empty($role_id))returnfalse;
returnSingleTableCRUD::delete($this->tbRefResourcesRoles,array("role_id"=>(int)$role_id));
}
/**
*为角色分配资源,每次均先全部移除表中相关记录再插入
*
*@paramint$role_id
*@parammixed$rsids
*
*@returnboolean
*/
functionallocateResourcesForRole($role_id,$rsids){
if(empty($role_id))returnfalse;
$role_id=(int)$role_id;
$rsids=normalize($rsids,",");
if(empty($rsids)){
returnfalse;
}
SingleTableCRUD::delete($this->tbRefResourcesRoles,array("role_id"=>$role_id));
$rsids=array_unique($rsids);
foreach($rsidsas$rsid){
SingleTableCRUD::insert($this->tbRefResourcesRoles,array("rsid"=>$rsid,"role_id"=>$role_id));
}
returntrue;
}
/**
*为用户指派角色,每次均先全部移除表中相关记录再插入
*
*此处在用户很多的时候可能会有性能问题...后面再想怎么优化
*
*@paramint$user_id
*@parammixed$roleIds
*
*@returnboolean
*/
functionallocateRolesForUser($user_id,$roleIds){
if(empty($user_id))returnfalse;
$user_id=(int)$user_id;
$roleIds=normalize($roleIds,",");
if(empty($roleIds)){
returnfalse;
}
SingleTableCRUD::delete($this->tbRefUsersRoles,array("user_id"=>$user_id));
$roleIds=array_unique($roleIds);
foreach($roleIdsas$roleId){
SingleTableCRUD::insert($this->tbRefUsersRoles,array("user_id"=>$user_id,"role_id"=>$role_id));
}
returntrue;
}
/**
*清除用户的角色信息
*
*@paramint$user_id
*
*@returnboolean
*/
functioncleanRolesForUser($user_id){
if(empty($user_id))returnfalse;
returnSingleTableCRUD::delete($this->tbRefUsersRoles,array("user_id"=>(int)$user_id));
}
/**
*清除角色的用户关联
*
*@paramint$role_id
*
*@returnboolean
*/
functioncleanUsersForRole($role_id){
if(empty($role_id))returnfalse;
returnSingleTableCRUD::delete($this->tbRefUsersRoles,array("role_id"=>(int)$role_id));
}
}
具体检测的代码如下:
/**
*对资源进行acl校验
*
*@paramstring$rsid资源标识
*@paramarray$user特定用户,不指定则校验当前用户
*
*@returnboolean
*/
functionaclVerity($rsid,array$user=null){
if(empty($rsid))returnfalse;
if(!CoreApp::$defaultAcl){
CoreApp::$defaultAcl=newAclFlat();
}
$rsRow=aclGetResource($rsid);
//未定义资源的缺省访问策略
if(!$rsRow)returnfalse;
CoreApp::writeLog($rsRow,"test");
$rsRow["access"]=AclBase::formatAccessValue($rsRow["access"]);
//允许任何人访问
if(AclBase::EVERYONE==$rsRow["access"])returntrue;
//不允许任何人访问
if(AclBase::NOBODY==$rsRow["access"])returnfalse;
//获取用户信息
if(empty($user))$user=isset($_SESSION["SI-SysUser"])?$_SESSION["SI-SysUser"]:null;
//用户未登录,则当成无访问权限
if(empty($user))returnfalse;
$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))
returntrue;
}
dump($user);
}
returnfalse;
}
/**
*对资源进行acl校验
*
*@paramstring$rsid资源标识
*@paramarray$user特定用户,不指定则校验当前用户
*
*@returnboolean
*/
functionaclVerity($rsid,array$user=null){
if(empty($rsid))returnfalse;
if(!CoreApp::$defaultAcl){
CoreApp::$defaultAcl=newAclFlat();
}
$rsRow=aclGetResource($rsid);
//未定义资源的缺省访问策略
if(!$rsRow)returnfalse;
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"])returntrue;
//不允许任何人访问
if(AclBase::NOBODY==$rsRow["access"])returnfalse;
//获取用户信息
if(empty($user))$user=isset($_SESSION["SI-SysUser"])?$_SESSION["SI-SysUser"]:null;
//用户未登录,则当成无访问权限
if(empty($user))returnfalse;
$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))
returntrue;
}
dump($user);
}
returnfalse;
}
/**
*重新生成角色资源访问控制表
*
*@paramstring$actTableACL表名称
*@paramboolean$return是否返回重新生成的列表
*
*@returnmixed
*/
functionaclRebuildACT($actTable,$return=false){
if(empty($actTable))returnfalse;
global$globalConf;
$rst=null;
$cacheId=null;
switch($actTable){
caseCoreApp::$defaultAcl->tbResources:
$cacheId="acl-resources";
$rst=SingleTableCRUD::findAll(CoreApp::$defaultAcl->tbResources);
//转成哈希表结构
if($rst){
$rst=array_to_hashmap($rst,"rsid");
}
break;
caseCoreApp::$defaultAcl->tbRoles:
$cacheId="acl-roles";
$rst=SingleTableCRUD::findAll(CoreApp::$defaultAcl->tbRoles);
//转成哈希表结构
if($rst){
$rst=array_to_hashmap($rst,"id");
}
break;
caseCoreApp::$defaultAcl->tbRefResourcesRoles:
$cacheId="acl-roles_has_resources";
$rst=SingleTableCRUD::findAll(CoreApp::$defaultAcl->tbRefResourcesRoles);
if($rst){
$_=array();
foreach($rstas$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;
}
/**
*获取角色资源访问控制表数据
*
*@paramstring$actTableACL表名称
*
*@returnmixed
*/
functionaclGetACT($actTable){
if(empty($actTable))returnfalse;
static$rst=array();
$cacheId=null;
switch($actTable){
caseCoreApp::$defaultAcl->tbResources:
$cacheId="acl-resources";
break;
caseCoreApp::$defaultAcl->tbRoles:
$cacheId="acl-roles";
break;
caseCoreApp::$defaultAcl->tbRefResourcesRoles:
$cacheId="acl-roles_has_resources";
break;
}
if(!$cacheId)returnnull;
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];
}
/**
*获取资源记录
*
*@paramstring$rsid
*
*@returnarray
*/
functionaclGetResource($rsid){
static$rst=null;
if(!$rst){
$rst=aclGetACT(CoreApp::$defaultAcl->tbResources);
if(!$rst)$rst=array();
}
returnisset($rst[$rsid])?$rst[$rsid]:null;
}
/**
*获取角色记录
*
*@paramint$role_id
*
*@returnarray
*/
functionaclGetRole($role_id){
static$rst=null;
if(!$rst){
$rst=aclGetACT(CoreApp::$defaultAcl->tbRoles);
if(!$rst)$rst=array();
}
returnisset($rst[$role_id])?$rst[$role_id]:null;
}
/**
*获取用户角色关联记录,此方法可以校验资源是否可被此角色调用
*
*@paramstring$rsid
*@paramint$role_id
*
*@returnarray
*/
functionaclGetRefResourcesRoles($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);
returnisset($rst[$ref_id])?$rst[$ref_id]:null;
}
http://code.google.com/p/php-excel/downloads/list迷你好用的EXCELxml输出方案
相关文章
- uni-app+php+workman实现简单聊天功能之聊天模块封装
- 带你一步步用php实现redis分布式、高并发库存问题
- 操作快速又简单:PHP进行MySQL数据库操作(php写mysql数据库)
- 以PHP、MySQL 管理图片:实现一手网络图库管理(php图片mysql)
- PHP使用Redis扩展连接Redis服务(php开启redis)
- 使用PHP操作Redis实例:简单高效的数据存储方案(php操作redis实例)
- PHP如何获取MySQL版本?(php获取mysql版本)
- PHP添加MySQL扩展:快速实现数据库连接(php添加mysql扩展)
- PHP连接MSSQL实现数据库操作(php用mssql)
- PHP实现连接MS SQL数据库的实战指南(php 打开mssql)
- PHP与MSSQL的良好结合,发挥强大的功能(php和mssql)
- PHP操作Redis队列实现数量控制(redis队列数量php)
- PHP实现高效的Redis连接(redis连接 php)
- PHP实现多服务器session共享之NFS共享的方法
- php来访国内外IP判断代码并实现页面跳转
- 20个非常有用的PHP类库加速php开发
- 《PHP编程最快明白》第三讲:php数组
- PHP第一节php简介
- php下拉选项的批量操作的实现代码
- php实现基于微信公众平台开发SDK(demo)扩展的方法
- 使用PHP实现阻止用户上传成人照片或者裸照
- PHP简单实现“相关文章推荐”功能的方法
- php实现最简单的MVC框架实例教程