我正在编写一个ACL类,它从“setter”方法中获取规则:
<?php
$acl = new AccessControlList();
$acl->allow('someController', 'publicAction', 'guestRole');
$acl->deny('someController', 'privateAction', 'guestRole');
问题是:在ACL对象中存储这些规则的最佳选择是什么?
目前,我正在考虑这样一个阵列:
array(
'guest' => array(
'someController' => array(
'publicAction' => true,
'privateAction' => false
)
),
'admin' => array (
...
)
)
但看起来它会在性能灾难发生时增长,记住读取数组的逻辑(推断isAllowed(...)
结果)并编写它(带有规则冲突,覆盖,角色和资源之间的继承) ...)。
也许我从一开始就错了,那些“制定者”就是问题所在。 是否有完善的设计模式可供使用?
答案 0 :(得分:1)
您可以通过延迟加载来避免填充整个ACL列表。
这是一种非常简单的方法,但概念应该扩展。这假设对于给定的请求,大多数(如果不是所有)acl检查将针对单个用户角色,但是相同的技术可以用于控制器或角色和控制器的组合。
以表格方式(csv,json,ini,db table或php include)定义acl,无论如何都可以获得,包含allow或deny,action和role的数组。我将使用php include,因为它假设最少。对于每个角色,您将拥有其中一个。
return array(
array("allow", "someController", "someAction"),
array("deny", "someController", "someOtherAction")
);
在AccessControlList上添加一个方法来读取和处理这样的文件。
protected function readConfig($role, $source){
$dat = include($source);
foreach($dat as $rule){
switch($rule[0]){
case "allow": $this->allow($rule[2], $rule[3], $role); break;
case "deny": $this->deny($rule[2], $rule[3], $role); break;
}
}
}
添加将角色绑定到文件的方法。这只会添加到您现有的acl
public function setRules($role, $source){
$this->acl[$role] = $source;
}
然后在isAllowed中检查角色的acl节点是字符串还是数组
public function isAllowed($role, $subject, $action){
if (is_string($this->acl[$role])){
$this->readConfig($role, $this->acl[$role]);
}
// do your acl check as normal.
}