2013-06-11 3 views
1

Я пишу класс ACL, который принимает свои правила из методов «инкубационных»:Как управлять правилами 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 (
     ... 
    ) 
) 

Но, похоже, это будет катастрофой производительности, когда он растет, имея в виду логику, чтобы прочитать массив (infering isAllowed(...) результаты) и его запись (с конфликтами правил, перезаписыванием, наследованием между ролями и ресурсами ...).

Возможно, я ошибаюсь с самого начала, и эти «сеттеры» являются проблемой. Есть ли какой-либо хорошо установленный шаблон дизайна?

+1

Вы смотрели на 'zend_acl'? Могу дать вам некоторое представление – AlexP

+0

Lazy загружает правила ACL. – Orangepill

+0

@AlexP Фактически моя реализация - это минималистическая версия 'zend_acl' (если я действительно понял, как это работает). Проблема в том, что я думаю, что все упрощение будет платить цену за этот беспорядочный массив. – albertedevigo

ответ

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. 
} 
+0

Если я понял, ваше решение зависит от наличия независимых файлов для каждой роли. Конечно, это вариант, но вы дали мне идею хранения правил в уникальном файле и фильтрации их (по ролям и ресурсам) в методе 'readConfig' - без метода setRules. Теперь я думаю, что суть состоит в том, чтобы отделить набор правил от объекта ACL, который открывает множество способов выбора области действия из всех правил. Это мне подходит :) – albertedevigo

Смежные вопросы