2.3. Продвинутое использование

2.3.1. Постоянное хранение данных ACL

Zend_Acl спроектирован таким образом, что не требует для хранения данных ACL использования определенных технологий хранения - таких, как база данных или сервер кеша. Его реализация на чистом PHP позволяет создавать административные инструменты под управлением Zend_Acl с относительной простотой и гибкостью. Многие ситуации требуют некоторой интерактивной поддержки от ACL, и Zend_Acl предоставляет методы для настройки, произведения запросов, контроля доступа приложением.

Тем не менее, хранение данных ACL остается задачей разработчика, т.к. случаи использования могут сильно варьироваться в различных ситуациях. Поскольку Zend_Acl доступен для сериализации, то можно сериализовать объекты ACL через PHP-функцию serialize(), и результаты можно хранить там, где пожелает разработчик - например, в файле, базе данных или с помощью механизма кэширования.

2.3.2. Написание условных правил ACL с утверждениями

Иногда правило разрешения или запрета доступа Роли к Ресурсу должно быть не безусловным, а зависеть от различных критериев. Например, определенный доступ должен быть разрешен, но только с 8:00 до 17:00. Другой пример - доступ должен быть запрещен, если запрос поступил с IP-адреса, находящегося в "черном списке". В Zend_Acl имеет встроеную поддержку для применения правил, основанных на любых нужных разработчику условиях.

Zend_Acl предоставляет поддержку условных правил с помощью интерфейса Zend_Acl_Assert_Interface. Чтобы использовать интерфейс утверждений, разработчик должен написать класс, который реализует метод assert() интерфейса:

<?php
require_once 'Zend/Acl/Assert/Interface.php';

class CleanIPAssertion implements Zend_Acl_Assert_Interface
{
    public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null,
                           Zend_Acl_Resource_Interface $resource = null, $privilege = null)
    {
        return $this->_isCleanIP($_SERVER['REMOTE_ADDR']);
    }

    protected function _isCleanIP($ip)
    {
        // ...
    }
}

После объявления класса утверждения разработчик должен передавать экземпляр этого класса при определении условных правил. Правило, которое создается с утверждением, применяется только тогда, когда метод утверждения возвращает true.

<?php
require_once 'Zend/Acl.php';

$acl = new Zend_Acl();
$acl->allow(null, null, null, new CleanIPAssertion());

Представленный выше код создает условное правило, которое разрешает всем доступ ко всем привилегиям всех ресурсов, за исключением случаев, когда IP-адрес запрашивающего занесен в "черный список". Если запрос приходит с IP-адреса, который не определяется как "белый", то правило не применяется. Поскольку правило применяется ко всем Ролям, всем Ресурсам и всем привилегиям, то "черный" IP приведет к запрещению доступа. Тем не менее, это особый случай, и следует понимать, что во всех других случаях (например, когда для правила были указаны Роль, Ресурс, или привилегия), невыполнение утверждения приводит к тому, что правило не применяется, и для определения того, реазрешить ли доступ или запретить, могут использоваться другие правила.

Методу assert() объекта утверждения передаются ACL, Роль, Ресурс и привилегия, к которым применяется запрос на авторизацию (например, isAllowed()). Это нужно для предоставления контекста классу утверждения и определения его условий там, где это нужно.