Как управлять правилами 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 ответ

Решение

Вы можете избежать заполнения списка ACL путем ленивой загрузки.

Это очень упрощенный подход, но концепция должна масштабироваться. Это предполагает, что для данного запроса большинство, если не все проверки ACL будут относиться к роли одного пользователя, но тот же метод может быть использован для контроллера или комбинации роли и контроллера.

Определите acl в табличном виде (csv, json, ini, db table или php include) независимо от того, что вы можете просто получить, массив, содержащий разрешения или запреты, действие и роль. Я собираюсь пойти с включением 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. 
}
Другие вопросы по тегам