Home  >  Article  >  Backend Development  >  Implementing a simple ACL in PHP - Completed_PHP Tutorial

Implementing a simple ACL in PHP - Completed_PHP Tutorial

WBOY
WBOYOriginal
2016-07-21 15:24:24736browse

复制代码 代码如下:

-- 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 allowed to access
*/
const NOBODY = 0;

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

/**
* Allow users with role 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 permissions 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);
}

/**
* Modify resources and return success status
*
* @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 role record primary key
*
* @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 the resource 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, each time remove all relevant records from the table 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;
}

/**
* Assign roles to users, and remove all relevant records from the table each time before inserting
*
* 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));
}

}

具体 检测的代码 如下:
复制代码 代码如下:

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

// 未定义资源的缺省访问策略
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']);

/**
* 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;

// --- 对用户进行 资源 <-> 角色 校验
if ($userHasRoles){
foreach ($user['roles'] as $role_id){
if ( aclGetRefResourcesRoles($rsid,$role_id) )
return true;
}
dump($user);
}
return false;
}

复制代码 代码如下:

/**
* 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 * Continue to verify other attributes below
* 2. Get the role id set from the session (or user session table)
* 3. If the user has a role, then 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 of 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;

// --- Resource<-> role verification for users
if ($userHasRoles){
foreach ($user['roles'] as $role_id){
if ( aclGetRefResourcesRoles( $rsid,$role_id) )
return true;
}
dump($user);
}
return false;
}
/**
* Regenerate the 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 输出方案

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/324286.htmlTechArticle复制代码 代码如下: -- ACL Tables -- 表的结构 `aclresources` DROP TABLE IF EXISTS `aclresources`; CREATE TABLE IF NOT EXISTS `aclresources` ( `rsid` varchar(64) NOT NULL...
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