Глава 2. Zend_Acl
Пред. |  | След.

## Глава 2. Zend_Acl

## 2.1. Введение

Zend_Acl предоставляет легкую и гибкую функциональность списка прав доступа (ACL) и управления привилегиями. Вообще, приложение может использовать данную функциональность для контроля доступа одних объектов к другим - защищенным.

В рамках данной документации,

- Ресурс - объект, доступ к которому контролируется.

- Роль - объект, который может запросить доступ к Ресурсу.

Попросту говоря, Роли запрашивают доступ к Ресурсу. Например, если человек запрашивает доступ к автомобилю, тогда человек - это Роль, а автомобиль - Ресурс, до тех пор пока доступ к автомобилю под контролем.

Благодаря спецификации и использованию списка прав доступа(ACL), приложение получает контроль над тем, как запращивающие объекты (Роли) получают доступ к защищенным объектам (Ресурсам).

### 2.1.1. О Ресурсах

В Zend_Acl создавать Ресурс очень просто. Zend_Acl предоставляет `Zend_Acl_Resource_Interface`, чтобы облегчить разработчикам процесс создания Ресурса. Класс должен только реализовать этот интерфейс, который состоит из одного метода, `getResourceId()`, для того, чтобы Zend_Acl рассматривал объект как Ресурс. Дополнительно, Zend_Acl также содержит `Zend_Acl_Resource`, как базовый класс, который разработчики могут расширять по желанию.

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

Zend_Acl также поддерживает права доступа к Ресурсам (например, "создание", "чтение", "обновление", "удаление"), и разработчик может закреплять правила, которые будут влиять на все или определенные права доступа к Ресурсу.

### 2.1.2. О Ролях

Как и в случае с Ресурсами, создавать Роль также очень просто. Zend_Acl предоставляет `Zend_Acl_Role_Interface` чтобы облегчить разработчикам процесс создания Ролей. Класс должен только реализовать этот интерфейс, который состоит из одного метода, `getRoleId()`, для того, чтобы Zend_Acl рассматривал объект как Роль. Дополнительно, Zend_Acl также содержит `Zend_Acl_Role`, как базовый класс, который разработчики могут расширять по желанию.

В Zend_Acl Роль может наследоваться от одной или от нескольких Ролей. Это реализовано для поддержки наследования правил между Ролями. Например, пользовательская Роль, такая как "салли", может принадлежать одной или нескольким родительским Ролям, таким как "редактор" и "администратор". Разработчик может привязывать правила к "редактору" и администратору раздельно, и "салли" будет наследовать правила обоих Ролей. Нет необходимости привязывать правила непосредственно к "салли".

| Замечание
Так как Zend_Acl поддерживает наследование правил от множества Ролей, существует вероятность возникновения конфликтов между ними, таким образом возникает необходимость однозначного решения конфликтных ситуаций. Zend_Acl решает такие конфликты присваивая наибольший приоритет Ролям, от которых Роль наследовалась в самую последнюю очередь. Поэтому, как только правило найдено для родительской Роли, от которой произошло наследование в последний момент, никакие другие правила не рассматриваются, так как правило с наибольшим приоритетом уже найдено.

### 2.1.3. Создание списка контроля доступа (ACL)

ACL может представлять любое множество физических либо виртуальных объектов. В целях демонстрации, мы создадим базовую функциональность ACL для Системы Управления Контентом (CMS), которая будет поддерживать нескольких уровней групп к множеству областей. Для создания объекта ACL, мы будем использовать ACL без параметров:

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

    $acl = new Zend_Acl();

| Замечание
По умолчанию Zend_Acl реализует "белый список", это значит, что пока обратное не указано разработчиком, Zend_Acl запрещает доступ ко всем Ресурсам для всех Ролей

### 2.1.4. Регистрация Ролей

Система Управления Контентом почти всегда нуждается в иерархии доступа для определения авторских возможностей своих пользователей. Это может быть группа "Гость", предоставляющая ограниченный доступ для демонстрации, группа "Посетитель" - группа большинства пользователей CMS, которые производят каждодневные операции, группа "Редактор" - для тех кто публикует и редактирует, архивирует и удаляет контент, и, наконец, группа "Администратор", участники группы могут выполнять все те же операции, что и участники других групп, а также управлять другой, специфической, информацией, пользователями, конфигурацией адинистративной части, а также делать резервное копирование/восстановление данных. Этот набор прав доступа может быть представлен в реестре Ролей, позволяя каждой группе наследовать привелегии родительской группы, при этом имея индивидуальные права доступа. Права доступа могут быть представлены в таком виде:

Таблица 2.1. Контроль доступа для демонстрационной CMS

Название | Индивидуальные права | Права унаследованные от
--- | --- | ---
Гость | Просмотр | Не определено
Посетитель | Редактирование, предложение на публикацию, исправление | Гость
Редактор | Публикация, архивирование, удаление | Посетитель
Администратор | (Обладает всеми правами) | Не определено

Для этого примера мы используем `Zend_Acl_Role`, но можно было использовать любой класс, который реализует интерфейс `Zend_Acl_Role_Interface`. Эти группы могут быть добавлены в реест Ролей таким образом:

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

    $acl = new Zend_Acl();

    //Добавить группы в реестр Ролей используя Zend_Acl_Role
    <!--
    // Add groups to the Role registry using Zend_Acl_Role
     -->
    require_once 'Zend/Acl/Role.php';

    // Гость не наследует управление доступом
    <!--
    // Guest does not inherit access controls
     -->
    $roleGuest = new Zend_Acl_Role('guest');
    $acl->addRole($roleGuest);

    //Посетитель наследуется от Гостя
    <!--
    // Staff inherits from guest
     -->
    $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);

    /*
    Альтернатива тому, что написано выше:
    <!--
    alternatively, the above could be written:
     -->
    $roleGuest = $acl->addRole(new Zend_Acl_Role('staff'), 'guest');
    //*/

    //Редактор наледуется от Посетителя
    <!--
    // Editor inherits from staff
     -->
    $acl->addRole(new Zend_Acl_Role('editor'), 'staff');

    //Администатор не наследует управление доступом
    <!--
    // Administrator does not inherit access controls
     -->
    $acl->addRole(new Zend_Acl_Role('administrator'));

### 2.1.5. Defining Access Controls

Now that the ACL contains the relevant Roles, rules can be established that define how Resources may be accessed by Roles. You may have noticed that we have not defined any particular Resources for this example, which is simplified to illustrate that the rules apply to all Resources. Zend_Acl provides an implementation whereby rules need only be assigned from general to specific, minimizing the number of rules needed, because Resources and Roles inherit rules that are defined upon their ancestors.

Consequently, we can define a reasonably complex set of rules with a minimum amount of code. To apply the base permissions as defined above:

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

    $acl = new Zend_Acl();

    require_once 'Zend/Acl/Role.php';

    $roleGuest = new Zend_Acl_Role('guest');
    $acl->addRole($roleGuest);
    $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
    $acl->addRole(new Zend_Acl_Role('editor'), 'staff');
    $acl->addRole(new Zend_Acl_Role('administrator'));

    // Guest may only view content
    $acl->allow($roleGuest, null, 'view');

    /* alternatively, the above could be written:
    $acl->allow('guest', null, 'view');
    //*/

    // Staff inherits view privilege from guest, but also needs additional privileges
    $acl->allow('staff', null, array('edit', 'submit', 'revise'));

    // Editor inherits view, edit, submit, and revise privileges from staff,
    // but also needs additional privileges
    $acl->allow('editor', null, array('publish', 'archive', 'delete'));

    // Administrator inherits nothing, but is allowed all privileges
    $acl->allow('administrator');

The `null` values in the above `allow()` calls are used to indicate that the allow rules apply to all Resources.

### 2.1.6. Querying the ACL

We now have a flexible ACL that can be used to determine whether requesters have permission to perform functions throughout the web application. Performing queries is quite simple using the `isAllowed()` method:

    <?php
    echo $acl->isAllowed('guest', null, 'view') ?
         "allowed" : "denied"; // allowed

    echo $acl->isAllowed('staff', null, 'publish') ?
         "allowed" : "denied"; // denied

    echo $acl->isAllowed('staff', null, 'revise') ?
         "allowed" : "denied"; // allowed

    echo $acl->isAllowed('editor', null, 'view') ?
         "allowed" : "denied"; // allowed because of inheritance from guest

    echo $acl->isAllowed('editor', null, 'update') ?
         "allowed" : "denied"; // denied because no allow rule for 'update'

    echo $acl->isAllowed('administrator', null, 'view') ?
         "allowed" : "denied"; // allowed because administrator is allowed all privileges

    echo $acl->isAllowed('administrator') ?
         "allowed" : "denied"; // allowed because administrator is allowed all privileges

    echo $acl->isAllowed('administrator', null, 'update') ?
         "allowed" : "denied"; // allowed because administrator is allowed all privileges

Пред. |  | След.
1.9. Zend::initRegistry($registry = 'Zend_Registry') | Начало | 2.2. Refining Access Controls