如何管理ACL规则?

时间:2013-06-11 16:48:00

标签: php design-patterns acl

我正在编写一个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(...)结果)并编写它(带有规则冲突,覆盖,角色和资源之间的继承) ...)。

也许我从一开始就错了,那些“制定者”就是问题所在。 是否有完善的设计模式可供使用?

1 个答案:

答案 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. 
}