Содержание


Acl


Permissions,Acl, ЗФ2, Zend Framework 2, ZF2, ру, ru




Компонент Zend\Permissions\Acl  предоставляет легкий и гибкий доступ к управлению доступом (ACL) на основе разрешений. Тоесть, при использовании в приложении появляется возможность контролировать уровень доступа к различным защищенным объектам.

 

Основные понятия:

- ресурсы (resource) – это объекты, доступ к которым контролируется.

- роли (role) – объекты, которые могут получить доступ к запрашиваемому ресурсу.

 

Например, на стоянке, владелец авто – выступает ролью, а сама машина -  ресурсом. Так как права доступа к ней есть только у водителя, а не у всех подряд.

 

Так же, используя ACL  в Вашем приложении есть возможность указывать какие роли имеют доступ к каким ресурсам и взаимосвязи между ролями и правами доступа.

 


Ресурсы

 

Создание ресурса используя Zend\Permissions\Acl\Acl является очень простой задачей. Интерфейс Zend\Permissions\Acl\Resource\ResourceInterface предусмотрен для облегчения создания ресурсов. Нужно просто, что б класс реализовал этот интерфейс, который содержит всего один метод «getResourceId()» для того, что б Zend\Permissions\Acl\Acl мог распознать объект как ресурс.  Так же предусмотрен  Zend\Permissions\Acl\Resource\GenericResource как базовая реализация для разработчиков, которая может быть расширена при необходимости.

 

Zend\Permissions\Acl\Acl предоставляет древовидную структуру, в которую могут добавляться множество ресурсов.  После добавления ресурса в это дерево, ресурсы могут быть размешены или в корне (общие), или в листьях (конкретные) . При обращении к конкретному ресурсу автоматически происходит сканирование всей иерархии для назначения соответствующих правил доступа.

 

Например, если правило применяется к каждому зданию в городе, то можно просто назначить правило на город, вместо применения его к каждому зданию . однако, если для какого то правило нужно дополнительное правило, то это легко добавляется с помощью Zend\Permissions\Acl\Acl для каждого здания при необходимости.

 

Каждый ресурс может наследовать только от одного ресурса, который в свою очередь тоже может наследовать от другого и т.д.

 

В Zend\Permissions\Acl\Acl так же существуют и привилегии ресурсов. Например: чтение, создание, обновление, удаление и т.д. У разработчика появляется назначать правила доступа на ресурсы с учетом привилегий.

 


Роли

 

Как и создание ресурсов, создание ролей так же очень просто. Все роли должны реализовать Zend\Permissions\Acl\Role\RoleInterface. Этот интерфейс состоит из одного метода «getRoleId()». А Zend\Permissions\Acl\Role\GenericRole создан как базовый класс для создания ролей разработчиками с возможностью дальнейшего расширения при необходимости.

 

В Zend\Permissions\Acl\Acl роли могут наследовать от одной или большего числа ролей. Например, роль «sally» может наследовать роли «editor» и «administrator». Разработчик может назначить разные права ролям «editor» и «administrator», а роль «sally» будет иметь объединенные права.

 

Однако множественно наследование усложняет разработку. Далее мы рассмотрим возможные ситуации неопределенности и как Zend\Permissions\Acl\Acl решает эти проблемы.

 


Множественное наследование ролей

 

В коде, приведенном ниже объявляются три основных роли: «guest», «member», «admin». Наследование может происходить от этих ролей. Затем, роль «someUser» создается и наследует других трех ролей. Порядок, в котором задаются роли в массиве «$parents» важен. При необходимости, Zend\Permissions\Acl\Acl ищет права не только для определенной роли «someUser», а и для ролей, которые она в свою очередь наследует (: «guest», «member», «admin»):

use Zend\Permissions\Ac\lAcl;
use Zend\Permissions\Acl\RoleGenericRole as Role;
use Zend\Permissions\Acl\ResourceGenericResource as Resource;
 
$acl = new Acl();
 
$acl->addRole(new Role('guest'))
    ->addRole(new Role('member'))
    ->addRole(new Role('admin'));
 
$parents = array('guest', 'member', 'admin');
$acl->addRole(new Role('someUser'), $parents);
 
$acl->addResource(new Resource('someResource'));
 
$acl->deny('guest', 'someResource');
$acl->allow('member', 'someResource');
 
echo $acl->isAllowed('someUser', 'someResource') ? 'allowed' : 'denied';

Никаких правил, непосредственно для роли  «someUser» и ресурса «someResource» не объявляется. Zend\Permissions\Acl\Acl должна найти правила, которые обявляются для ролей, которые наследует «someUser». Сначала исследуется роль «admin», но для нее никаких правил не назначено. Потом «member» и Zend\Permissions\Acl\Acl определеяет, что для нее есть правило.: открыт доступ к ресурсу «someResource».

 

Если же Zend\Permissions\Acl\Acl продолжит поиск, то определит, что роли «guest»  наоборот, закрыт доступ к ресурсу «someResource». Это вносит некоторую неопределенность, потому что на данный момент «someUser» одновременно и имеет доступ и не имеет доступ к «someResource».

 

Zend\Permissions\Acl\Acl разрешает данную неопределенность тем, что при нахождении первого правила, применяющегося к данному запросу останавливает поиск. И так как, роль «member» объявлена перед ролью «guest», то приведенный пример выдаст: «allowed» (разрешено).

 

Важно: Определяя множество ролей как родителей, не забывайте, что поиск прав происходит с конца. Тоесть первой начнет сравниваться последняя объявленная роль.

 

Создание списка контроля доступа

 

Создание списка контроля доступа - Access Control List (ACL) – может представлять любое количество физических или виртуальных объектов. Для демонстрации, мы создадим Content Management System (CMS) ACL, которая будет содержать несколько групп в различных областях .Для создания объекта ACL  создадим ACL без параметров.

use Zend\Permissions\Acl\Acl;
$acl = new Acl();

Важно: Пока разработчик сам не установит  правило «allow» (разрешить), Zend\Permissions\Acl\Acl по умолчанию считает, что доступ закрыт для всех ролей.

 

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

 

В CMS практически всегда необходимо создавать иерархию разрешений для определения прав пользователей. Например, это может быть группа «Guest» для обеспечения ограниченного доступа, группа «Staff»  - для большинства пользователей с необходимым набором функций, «Editor» - ответственные за размещение новостей, обзоров, статей, изменения и удаления контента, и «Administrator» - которые могут назначать права другим группам и пользователям, администрировать CMS, делать резервные копии  и т.д.  Такой набор прав доступа и разрешений может быть организован  как реестр ролей, позволяя каждой группе наследовать права от своих групп-родителей,  а так же предоставлять уникальные возможности каждой из групп.

 

Контроль доступа для описанной CMS:

Имя

Уникальные разрешения

Наследовать от

Guest

View

N/A

Staff

Edit

Guest

Editor

Publish, Archive, Delete

Staff

Administrator

Весь доступ

N/A

 

Данные группы могут быть организованы следующим образом:

use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\RoleGenericRole as Role;
 
$acl = new Acl();
 
// Add groups to the Role registry using ZendPermissionsAclRoleGenericRole
// Guest does not inherit access controls
$roleGuest = new Role('guest');
$acl->addRole($roleGuest);
 
// Staff inherits from guest
$acl->addRole(new Role('staff'), $roleGuest);
 
/*
Alternatively, the above could be written:
$acl->addRole(new Role('staff'), 'guest');
*/
 
// Editor inherits from staff
$acl->addRole(new Role('editor'), 'staff');
 
// Administrator does not inherit access controls
$acl->addRole(new Role('administrator'));

Определение контроля доступа

 

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

 

Zend\Permissions\Acl\Acl предоставляет такую реализацию, в которой правила должны предоставляться от общих к конкретным, тем самым минимализируя необходимое количество  правил.

 

Важно: Zend\Permissions\Acl\Acl всегда подчиняется переданному правилу. Исключением является передача более конкретного правила.

 

Следовательно, мы можем определить достаточно сложный набор правил с минимальным количеством кода:

use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\RoleGenericRole as Role;
 
$acl = new Acl();
 
$roleGuest = new Role('guest');
$acl->addRole($roleGuest);
$acl->addRole(new Role('staff'), $roleGuest);
$acl->addRole(new Role('editor'), 'staff');
$acl->addRole(new 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');

Передача значения «NULL»  при вызове метода «allow()» используется, что правило доступа «allow» (разрешить) применяется ко всем ресурсам.

 


Запросы к ACL

 

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

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

Автор статьи: DuB