1

我正在编写一个从“setter”方法中获取规则的 ACL 类:

<?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(...)结果)和写入数组的逻辑(规则冲突、覆盖、角色和资源之间的继承......)。

也许我从一开始就错了,那些“二传手”就是问题所在。是否有任何完善的设计模式可以遵循?

4

1 回答 1

1

您可以通过延迟加载来避免填充整个 ACL 列表。

这是一种非常简单的方法,但这个概念应该可以扩展。这假设对于给定的请求,如果不是所有的 acl 检查都将针对单个用户角色,但相同的技术可以用于控制器或角色和控制器的组合。

以表格方式(csv、json、ini、db 表或 php 包含)定义 acl,只要你能得到,一个包含允许或拒绝、操作和角色的数组。我将使用 php 包含,因为它假设最少。对于每个角色,您将拥有其中一个。

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. 
}
于 2013-06-11T18:46:22.327 回答