Zend_Acl часть 1 : Распространенные заблуждения и простые ACL
|
Опубликовано: 04.04.2009
|
- От переводчика
- Введение
- Распространенные заблуждения о Zend_Acl
- Построение простого ACL
- Использование простого ACL
- Использование простого ACL в Zend Framework приложениях
От переводчика
Данный тест - перевод статьи Zend_Acl part 1: Misconceptions and simple ACLs автором которой является Jani Hartikainen. Большое спасибо Александру Махомету, и Александру Стешенко за помощь в работе над переводом. Следующие части статьи в русскоязычном варианте находятся в обработке.
Введение
ACL - access control list (cписок прав доступа).
Я начинаю серию статей о Zend_Acl. Первая статья познакомит вас с азами Zend_Acl. Для этого мы развеем некоторые распространенные заблуждения и научимся создавать простые списки прав доступа (ACL). Затем применим ACL в приложениях на базе Zend Framework и в качестве независимого компонента.
В последующих статьях данной серии я затрону более сложные способы использования Zend_Acl. В частности использование Zend_Acl совместно с базой данных.
Распространенные заблуждения о Zend_Acl
Многие думают, что такие понятия как “resource" (ресурс) and “privilege" (привилегия) тождественны таким понятиям как "controller" (контроллер) и “action “ (экшен, действие). Это не так.
Ресурсом в Zend_Acl может быть всё что угодно: модель, контроллер, файл и т.д.
Аналогично привилегией может быть всё, что так или иначе связано с ресурсом. К примеру привилегией может быть действие, если ресурсом является контроллер. Или разрешение на «чтение» или «запись», если ресурсом является файл или модель.
В последующих статьях данной серии я расскажу о других способах использования ресурсов, привилегий и ролей.
Построение простого ACL
Как мы выяснили, Zend_Acl состоит из ресурсов (resources), привилегий (privileges) и ролей (roles). Ресурсом может быть абсолютно всё что угодно. Привилегиями являются различные уровни доступа к ресурсу. Ролями могут выступать пользователи, группы, и т.д. Роль определяет того, кто имеет доступ к ресурсу и какими привилегиями он обладает.
Самый простой способ использования Zend_Acl заключается в настройке правил ACL в самом коде. В целом это довольно неплохой подход для простых случаев, то есть в тех случаях, когда у вас небольшое количество ролей и ресурсов.
class My_Acl extends Zend_Acl {
public function __construct() {
// Создание новой роли guest («гость»)
$this->addRole(new Zend_Acl_Role('guest'));
// Создание роли user («пользователь») которая наследует роль guest
$this->addRole(new Zend_Acl_Role('user'), 'guest');
// Создаём ресурс page («страница»)
$this->add(new Zend_Acl_Resource('page'));
// Создаём ресурс news («новости») который наследует ресурс «страницу»
$this->add(new Zend_Acl_Resource('news'), 'page');
// Разрешаем гостю просматривать страницы
$this->allow('guest', 'page', 'view');
// Разрешаем пользователю комментировать новости.
$this->allow('user', 'news', 'comment');
}
}
Создание нового экземпляра объекта My_Acl позволит проводить простые проверки доступа согласно ACL. Давайте разберём этот пример подробно.
Роль guest («гость») получает привилегию view («просмотр») на доступ к ресурсу page («страница»). Роль «пользователь» наследует роль «гость», соответственно роль «пользователь» наследует и привилегии роли «гость». Аналогично ресурс «новости» наследует ресурс «страница». Таким образом, все у кого есть привилегии на доступ к ресурсу «страница» автоматически имеют такие же привилегии и к ресурсу «новости». В конце мы добавили «пользователю» привилегию комментирования «новостей». Таким образом, только обладатели роли «пользователь» имеют привилегию комментировать новости.
Обратите внимание: имена, которые были использованы для ролей и ресурсов являются просто идентификаторами. Они могут быть любыми. Например "1" или "2", в общем чем угодно. Но лучше использовать идентификаторы, которые интуитивно понятны. Однако когда вы генерируете ACL из базы данных или из другого источника, создание «удачных» имён может вызывать трудности, и не всегда на этом стоит заострять внимание. В таком случае неплохим идентификатором будет первичный ключ строки в таблице базы данных. Позже в статьях этой серии я познакомлю вас с подобным примером.
Использование простого ACL
Использовать класс ACL довольно просто. Всё что нужно сделать – это вызвать метод isAllowed() (проверка наличия права). Передав ему в качестве параметров роль, ресурс и привилегию. Основная сложность заключается в определении роли, ресурса и привилегии.
Как мы определим роль? Например, с помощью условного выражения. Если пользователь авторизирован, то его роль «пользователь», в противном случае - «гость».
Теперь разберёмся с ресурсом. В зависимости от приложения, мы можем выбрать имя ресурса, исходя из имени подключаемого файла. В нашем простом примере могут быть использованы файлы с именами page.php и news.php. Тогда ресурс «page» будет отвечать за page.php, а ресурс «news» - за news.php.
И наконец, привилегия. Когда вы загружаете страницу, вы можете проверить наличие привилегии просмотра. Затем по необходимости проверять наличие других привилегий. Например, вы можете вывести блок для комментирования новости, проверив у роли наличие привилегии «комментирования».
Небольшой пример:
$role = 'guest';
if(isset($_SESSION['auth']))
$role = 'user';
$acl = new My_Acl();
if($acl->isAllowed($role, 'news', 'comment')) {
// код для вывод блока комментирования
}
Как вы смогли убедиться, использовать Zend_Acl довольно просто. Даже без полноценного использования Zend Framework вы можете с лёгкостью ускорить разработку ваших приложений.
Наш пример очень прост, но он показывает основы использования ACL.
Использование простого ACL в Zend Framework приложениях.
В приложениях на основе Zend Framework ресурс и привилегия часто могут быть определены из обьекта запроса.
Создадим небольшой плагин который будет проверять ACL.
class My_Plugin_Acl extends Zend_Controller_Plugin_Abstract {
private $_acl = null;
public function __construct(Zend_Acl $acl) {
$this->_acl = $acl;
}
public function preDispatch(Zend_Controller_Request_Abstract $request) {
// Как и в предыдущем примере, аутентифицированные пользователи будут иметь
// роль «пользователь»
$role = (Zend_Auth::getInstance()->hasIdentity())
? 'user'
: 'guest';
// В этом примере мы будем использовать контроллер в качестве ресурса.
$resource = $request->getControllerName();
if(!$this->_acl->isAllowed($role, $resource, 'view')) {
// Если недостаточно прав то мы перенаправляем его на страницу авторизации
$request->setModuleName('auth')
->setControllerName('auth')
->setActionName('login');
}
}
}
Вместо того чтобы передавать ACL в качестве параметра конструктора мы могли сделать его статичным, или создать его в методе preDispatch. Однако, передача его в качестве параметра позволила упростить повторное использование плагина. Таким образом, если мы изменим класс ACL, наш плагин может остаться без изменений.
Теперь, создав плагин, добавим его во front controller в загрузчике.
$acl = new My_Acl();
// $fc – front controller
$fc->registerPlugin(new My_Plugin_Acl($acl));
Теперь каждый запрос будет проходить проверку ACL, и никто не сможет «пройти внутрь», не имея привилегии просмотра.
Обратите внимание: Если вы используете класс My_Acl «как есть», это может вызвать запуск бесконечного цикла! Код плагина перенаправляет вас на страницу авторизации. После этого проверяется доступ к странице. Для этого всё так же используется имя контроллера в качестве идентификатора ресурса. Но в My_Acl нет ресурса, который называется auth! Итак, если вы хотите чтобы этот пример заработал, вам необходимо добавить ресурс auth в ACL.и наследовать auth от page, так как «гость» уже имеет необходимые привилегии к ресурсу page.
Как проверить привилегию комментирования?
Вы можете добавить в контроллер код, который будет проверять наличие необходимой привилегии. Затем передать во view результат проверки в качестве булевой переменной.
public function someAction() {
$role = (Zend_Auth::getInstance()->hasIdentity())
? 'user'
: 'guest';
// Предполагаем что $this->_acl содержит acl
$this->view->canComment = $this->_acl->isAllowed($role, 'news', 'comment');
}
Будет неплохо изменить код таким образом, чтобы избежать двойной проверки роли. Например вы можете хранить роль в идентификаторе пользователя (прим переводчика Zend_Auth::getIdentity()) . Или создать action helper для доступа в ACL и содержащий все необходимые данные.
Тема на форуме
- Спрашивать почему у вас не работает код, для этого есть тема форума закрепленная за статьей.
- Спрашивать как реализовать ту или иную функциональность, для этого необходимо создать свою тему на форуме.
Комментарии для того чтобы: высказать свое аргументированное мнение о статье, указать какие участки вызывают непонимание, что нужно исправить/улучшить, просто сказать спасибо.
Комментарии имеют древовидную структуру.
Если вы хотите ответить на определенный комментарий - нажмите на ссылку "Ответить" возле этого комментария.

