Home  >  Article  >  Backend Development  >  Implement simple ACL in php

Implement simple ACL in php

高洛峰
高洛峰Original
2016-11-30 14:04:041185browse

代码如下: 
-- 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 , 
`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 (`id`), 
UNIQUE KEY `rolename` (`rolename`) 
)DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 
-- 表的结构 `ref_aclresources_aclroles` 
DROP TABLE IF EXISTS `ref_aclresources_aclroles`; 
CREATE TABLE IF NOT EXISTS `ref_aclresources_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 类 
 代码如下: 
/**
* Simple ACL permission control function
*
* Table definition
*
* 1. Resource definition (rsid, access, desc, created_at, updated_at)
* 2. Role definition (id, rolename, desc, created_at, updated_at)
* 3. Resource-role association (rsid, role_id)
* 4. User-role association (user_id, role_id)
*
* Depends on db.php sqlobject.php
*
* @author vb2005xu.iteye.com
*/ 
class AclBase { 
// --- ACL 访问授权 

/**
* No one is allowed to access
*/ 
const NOBODY = 0; 

/**
* Allow anyone to access
*/ 
const EVERYONE = 1; 

/**
* Allow users with roles to access
*/ 
const HAS_ROLE = 2; 

/**
* Allow users without roles to access
*/ 
const NO_ROLE = 3; 
/**
* Only roles defined in the resource-role association can access
*/ 
const ALLOCATE_ROLES = 4; 

// 定义相关的 表名 
public $tbResources = 'aclresources'; 
public $tbRoles = 'aclroles'; 
public $tbRefResourcesRoles = 'ref_aclresources_aclroles'; 
public $tbRefUsersRoles = 'ref_users_aclroles'; 

/**
* Format resource access rights and return
*
* @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; 


/**
* Create a resource and return the primary key of the resource record
*
* @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'); 


/**
* Delete resource
*
* @param string $rsid
* @return int
*/ 
function deleteResource($rsid){ 
if (empty($rsid)) return false; 
return SingleTableCRUD::delete($this->tbResources,array('rsid'=>$rsid)); 


/**
* Create a role and return the primary key of the role record
*
* @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); 


/**
* Modify the role and return the success status
*
* @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'); 


/**
* Delete role
*
* @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)); 


/**
* Specify roles for resources, and remove all relevant records in the table each time before inserting
*
* @param int $rsid
* @param mixed $roleIds
* @param boolean $setNull When the role id does not exist, Whether to clear resources from the association table
*/ 
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)); 


/**
* Allocate resources to roles, remove all relevant records in the table each time and then insert them
*
* @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; 


/** 
* 为用户指派角色,每次均先全部移除表中相关记录再插入 

* There may be performance issues here when there are many users... We will think about how to optimize it later
*
* @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 ;
}

/**
* Clear user’s role information
*
* @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));
}

/**
* Clear the user association of the role
*
* @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));
}

}

The specific detection code is as follows:
Copy code The code is as follows:
/**
* Perform acl verification on resources
*
* @param string $rsid resource identifier
* @param array $user specific user, if not specified, verify the current user
*
* @return boolean
*/
function aclVerity($rsid ,array $user = null){

if (empty($rsid)) return false;
if (!CoreApp::$defaultAcl) {
CoreApp::$defaultAcl = new AclFlat ();
}

$rsRow = aclGetResource($rsid);

// Default access policy for undefined resources
if (!$rsRow) return false;

CoreApp::writeLog($rsRow,'test ');

$rsRow['access'] = AclBase::formatAccessValue($rsRow['access']);

// Allow anyone to access
if (AclBase::EVERYONE == $rsRow['access' ]) return true;

// Do not allow anyone to access
if (AclBase::NOBODY == $rsRow['access']) return false;

// Get user information
if (empty($user)) $user = isset($_SESSION['SI-SysUser']) ? $_SESSION['SI-SysUser'] : null;

// If the user is not logged in, it is regarded as having no access rights
if (empty($user)) return false;

$user['roles'] = empty($user['roles']) ? null : normalize($user['roles'],';');

$userHasRoles = !empty($ user['roles']);

/**
* Allow users without roles to access
*/
if (AclBase::NO_ROLE == $rsRow['access']) return $userHasRoles ? false : true;

/**
* Allow users with roles to access
*/
if (AclBase::HAS_ROLE == $rsRow['access']) return $userHasRoles ? true : false;

// --- Resource<-> role verification for users
if ( $userHasRoles){
foreach ($user['roles'] as $role_id){
if ( aclGetRefResourcesRoles($rsid,$role_id) )
return true;
}
dump($user);
}
return false;
}

Copy code The code is as follows:
/**
* Perform acl verification on resources
*
* @param string $rsid resource identifier
* @param array $user specific user, if not specified, verify the current user
*
* @return boolean
*/
function aclVerity($rsid ,array $user = null){

if (empty($rsid)) return false;
if (!CoreApp ::$defaultAcl) {
CoreApp::$defaultAcl = new AclFlat();
}

$rsRow = aclGetResource($rsid);

// Default access policy for undefined resources
if (!$rsRow) return false;

CoreApp::writeLog($rsRow,'test');

/*
* The verification steps are as follows:
*
* 1. First verify the access attribute of the resource itself
* EVERYONE => true, NOBODY => false * Other attributes will continue to be verified below
* 2. Get the role id set from the session (or user session table)
* 3. If the user has a role, HAS_ROLE => true , NO_ROLE => false; vice versa
* 4. If resource access == ALLOCATE_ROLES
* 1. Get the role id set corresponding to the resource from the cache (or $tbRefResourcesRoles)
* 2. Find the intersection between the role id set owned by the user and the role id set corresponding to the resource
* 3. Intersection exists => true; otherwise => false
*/

$rsRow['access'] = AclBase::formatAccessValue($rsRow['access']);

// Allow anyone to access
if (AclBase::EVERYONE == $rsRow ['access']) return true;

//Do not allow anyone to access
if (AclBase::NOBODY == $rsRow['access']) return false;

// Get user information
if (empty( $user)) $user = isset($_SESSION['SI-SysUser']) ? $_SESSION['SI-SysUser'] : null;

// If the user is not logged in, it is regarded as having no access rights
if (empty( $user)) return false;

$user['roles'] = empty($user['roles']) ? null : normalize($user['roles'],';');

$userHasRoles = !empty($user['roles']);

/**
* Allow users without roles to access
*/
if (AclBase::NO_ROLE == $rsRow['access']) return $userHasRoles ? false : true;

/ **
* Allow users with roles to access
*/
if (AclBase::HAS_ROLE == $rsRow['access']) return $userHasRoles ? true : false;

// --- Perform resource calibration for users<-> Role calibration Check
if ($userHasRoles){
foreach ($user['roles'] as $role_id){
if ( aclGetRefResourcesRoles($rsid,$role_id) )
return true;
}
dump($user);
}
return false;
}
/**
* Regenerate role resource access control list
*
* @param string $actTable ACL table name
* @param boolean $return Whether to return the regenerated list
*
* @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);
//Convert to hash table structure
if ($rst){
$rst = array_to_hashmap($rst,'rsid');
}
break;
case CoreApp::$defaultAcl ->tbRoles:
$cacheId = 'acl-roles';
$rst = SingleTableCRUD::findAll(CoreApp::$defaultAcl->tbRoles);
// Convert to hash table structure
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;
}
/ **
* Get role resource access control list data
*
* @param string $actTable ACL table name
*
* @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];
}
/**
* Get resource record
*
* @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; 

/**
* Get role record
*
* @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; 

/**
* Get the user role association record. This method can verify whether the resource can be called by this role
*
* @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; 


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

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn