我正在为自定义框架的访问控制实现而苦苦挣扎.
不需要RBAC粒度,所以我决定采用某种资源的ACL
控制器动作.
这是数据库结构:
用户:
>约翰
>玛丽
>格雷格
user_groups:
>管理员
>会计师
>经理
users_to_user_groups:
>约翰=>管理员
>玛丽=>会计师
> Greg =>经理
资源(控制器动作):
resources_to_user_groups:
> users / edit =>管理员
>发票/添加=>会计师
> customers / delete =>经理
这是[伪]代码.
$user = new User; // This will be currently logged in user ...
$acl = new Acl($user);
$dispatcher = new dispatcher($acl);
$dispatcher->dispatch('users', 'new');
class dispatcher
{
public function dispatch($controller, $action)
{
$permission = $controller . '/' . $action;
if(!$this->acl->isAllowed($permission))
{
throw new AccessDeniedException("Access denied");
}
// User is authorized to execute this action, dispatch ...
}
}
我喜欢这种方法……直到我意识到还有许多XHR请求.
例如,发票清单使用XHR请求获取总金额,订单列表使用XHR请求
加载订单位置和其他数据等
因此,必须有一些资源分组,例如,新表resource_groups:
>发票清单(发票/清单,发票/ xhr_get_total_amount)
>订单清单(订单/清单,订单/ xhr_get_positons_for_order,订单/ xhr_get_some_other_data)
>添加新用户(users / new)#单一操作,新用户输入表单不使用XHR请求
感觉很复杂.这是正确的方法吗?有什么可以改进的?有没有框架解决这个问题?
解决方法:
在过去的一年里,我一直在处理同样的问题,这就是我如何处理它.
首先,我使用Zend Framework’s ACL库作为基本引擎告诉我某些用户是否可以访问某些资源.由于ZF已经支持用户分组和角色(包括角色层次结构),因此您不再需要担心这一点.
将用户分组和角色放在一边,接下来将是资源分组,ZF内部不支持(遗憾).我相信这是你的问题所关注的部分.然而,您可以使用ZF并扩展它以满足您的需求.您需要做的就是为资源(平面或分层)提供分组机制.然后您可以按照手册中的说明使用ZF.
以下是如何执行此操作的示例:
>构造ACL引擎和其他基本对象:
$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('guest'))
->addRole(new Zend_Acl_Role('member'))
->addRole(new Zend_Acl_Role('admin'));
$parents = array('guest', 'member', 'admin');
$acl->addRole(new Zend_Acl_Role('someUser'), $parents);
>定义资源分组:
$resources = array(
'group 1' => array(
'resource 1'
, 'resource 2'
, 'resource 3'
)
, 'group 2' => array(
'resource 1'
, 'resource 4'
, 'resource 5'
)
);
>将您的资源引入ACL的引擎:
function addResource(Zend_Acl $acl, $resources, $groupName)
{
foreach ($resources[$groupName] as $resource) {
$acl->add(new Zend_Acl_Resource($resource));
}
}
addResource($acl, $resources, 'group 2');
>使用ACL的引擎查询权限:
echo $acl->isAllowed('someUser', 'resource 1') ? 'allowed' : 'denied';
如你所见,我在这里没有做任何特别的事.这里介绍的唯一新概念是添加到ACL引擎的资源与用于查询它的资源不同.但是在我们实际调用ZF的库之前已经完成了一层,因此查询ZF的ACL的调用仍然有效.
我希望我能清楚地写下我的观点.不要忘记我只是想给你一个概念,你需要自己想出实际的实现.