zl程序教程

您现在的位置是:首页 >  后端

当前栏目

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输出方案