Интеграция Zend_Acl И Mvc. Часть 2 (Расширенный Вариант Использования)

На Девзона появился вторая часть статьи об интеграции Zend_Acl в MVC Мы с Альдемара Берналь спешим предложить вам ее перевод. В первая часть мы говорили о том, как настроить экземпляр Zend_Acl и включить его в среду MVC (с помощью плагина фронт-контроллера).

А как насчет настройки других действий по блокировке доступа или как сделать так, чтобы редактирование статьи делал только ее автор? Об этом и многом другом пойдет речь далее.

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



1. Использование модулей

Давайте поговорим о модулях.

В качестве примера для этой статьи мы взяли сайт, похожий на DevZone. А что, если мы создадим административный модуль, задачей которого будет реализация процедуры согласования статьи.

Кроме того, модуль может реализовать ряд других задач, например, управление короткими ссылками или категориями.

В этом случае нам придется изменить нашу модель ресурса: Общий модуль Пользовательский контроллер.

Контролер статей.

Административный модуль Контролер статей.

Контроллер короткой связи.

Контроллер категории.

На основе этой новой модели ресурсов мы создадим экземпляр Zend_Acl, который будет ее отражать.

Примечание : Помните, что этот код и создание экземпляра объекта Zend_Acl должны быть выполнены до вызова метода диспетчеризации фронт-контроллера (во время загрузки).

 /** Creating Roles */
 require_once 'Zend/Acl/Role.php';
 $myAcl->addRole(new Zend_Acl_Role('guest'))
       ->addRole(new Zend_Acl_Role('writer'), 'guest')
       ->addRole(new Zend_Acl_Role('admin'), 'writer');
 
 /** Creating resources */
 require_once 'Zend/Acl/Resource.php';
 /** Default module */
 $myAcl->add(new Zend_Acl_Resource('user'))
       ->add(new Zend_Acl_Resource('article'));
 
 /** Admin module */
 $myAcl->add(new Zend_Acl_Resource('admin'))
       ->add(new Zend_Acl_Resource('admin:article', 'admin'))
       ->add(new Zend_Acl_Resource('admin:quick-link', 'admin'))
       ->add(new Zend_Acl_Resource('admin:category', 'admin'));
 
 /** Creating permissions */
 $myAcl->allow('guest', 'user')
       ->deny('guest', 'article')
       ->allow('guest', 'article', 'view')
       ->allow(array('writer', 'admin'), 'article', array('add', 'edit'))
       ->allow('admin', 'admin');
 
 /** Setting up the front controller */
 require_once 'Zend/Controller/Front.php';
 $front = Zend_Controller_Front::getInstance();
 $front->setControllerDirectory(array('default' => 'path/to/default/controllers',
                                      'admin' => 'path/to/admin/controllers'));
 
 /** Registering the Plugin object */
 require_once 'Zend/Controller/Plugin/Acl.php';
 $front->registerPlugin(new Zend_Controller_Plugin_Acl($myAcl, 'guest')); 
 
 /** Dispatching the front controller */
 $front->dispatch();
Отмечу, что мы, как и раньше, создали ресурс для каждого контроллера.

Но в случае с модулем администратора мы создали ресурс для модуля и по одному для каждого контроллера внутри этого модуля в формате «модуль: контроллер», сделав их дочерними элементами ресурса модуля.

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



2. Использование ролей

После того как пользователь вошел в приложение, ему должна быть назначена роль.

В нашем примере этой ролью может быть «гость», «автор» или «администратор».

Но как мы можем изменить текущую роль ACL в нашем компоненте? Во-первых, вы должны сохранить эту роль в переменной в пространстве сеанса.

Поэтому, как только пользователь войдет в систему, вы должны сохранить роль пользователя в сеансе.

При следующем запросе вы возьмете эту переменную из сеанса и будете использовать ее для настройки плагина фронт-контроллера на этапе загрузки.

Пользовательский контроллер

 class UserController extends Zend_Controller_Action
 {
     protected $_application;
 
     public function init()
     {
         require_once 'Zend/Session/Namespace.php';
         $this->_application = new Zend_Session_Namespace('myApplication');
     }
 
     public function loginAction()
     {
         .

Validation code if ($valid) { /** Setting role into session */ $this->_application->currentRole = $user->role; $this->_application->loggedUser = $user->username; } } public function logoutAction() { $this->_application->currentRole = 'guest'; $this->_application->loggedUser = null; } }

Файл загрузчика
 /** Loading application from session */
 require_once 'Zend/Session/Namespace.php';
 $application = new Zend_Session_Namespace('myApplication');
 
 if (!isset($application->currentRole)) {
     $application->currentRole = 'guest';
 }
 
 /** Setting up the front controller */
 require_once 'Zend/Controller/Front.php';
 $front = Zend_Controller_Front::getInstance();
 $front->setControllerDirectory('path/to/controllers'); 
 
 /** Registering the Plugin object */
 require_once 'Zend/Controller/Plugin/Acl.php';
 $front->registerPlugin(new Zend_Controller_Plugin_Acl($myAcl, $application->currentRole));
 
 /** Dispatching the front controller */
 $front->dispatch();


3. Настройка действия при ошибке «доступ запрещен»

Возможно, некоторым из вас (надеюсь, никому =D) просто не нравится идея иметь действие «Доступ запрещен» в контроллере ошибок, или вы просто хотите назвать его как-нибудь по-другому.

Это можно сделать, вызвав метод setErrorPage плагина фронт-контроллера.

 /** Setting up the front controller */
 require_once 'Zend/Controller/Front.php';
 $front = Zend_Controller_Front::getInstance();
 $front->setControllerDirectory('path/to/controllers'); 
 
 /** Setting default access denied action */
 require_once 'Zend/Controller/Plugin/Acl.php';
 $aclPlugin = new Zend_Controller_Plugin_Acl($myAcl, 'guest');
 $aclPlugin->setErrorPage('goaway', 'my-error-controller', 'my-module'); 
 
 /** Registering the Plugin object */
 $front->registerPlugin($aclPlugin); 
 
 /** Dispatching the front controller */
 $front->dispatch();
Метод setErrorPage можно вызвать только с именем действия.

В этом случае контроллер и модуль останутся «ошибочными» и «по умолчанию».

Метод также можно вызвать, передав имена действия и контроллера или передав все три параметра.



4. Использование Помощника действий

Наконец, мы увидим одну из самых важных частей этого предложения.

До сих пор в нашем примере DevZone мы видели, что разрешаем администраторам и авторам редактировать статьи.

Но подождите, в нашем приложении все еще недостает части.

Теперь если я автор и имею доступ к статье/edit/:id, то это означает, что у меня есть доступ к редактированию не только своих статей, но и статей других авторов! Это не очень хорошо, не так ли? Так что же мы собираемся с этим делать? Мы будем управлять этим с помощью помощника действий, что означает, что вы сможете получить доступ к нашим спискам управления доступом внутри любого контроллера, а не только во время загрузки.

Итак, первое, что мы делаем, это регистрируем не только наш плагин фронт-контроллера, но и нашего помощника действий в Controller Action Helper Broker. Файл загрузчика

 /** Loading application from session */
 require_once 'Zend/Session/Namespace.php';
 $application = new Zend_Session_Namespace('myApplication');
 
 if (!isset($application->loggedUser)) {
     $application->loggedUser = null;
 }
 
 /** Setting up the front controller */
 require_once 'Zend/Controller/Front.php';
 $front = Zend_Controller_Front::getInstance();
 $front->setControllerDirectory('path/to/controllers'); 
 
 /** Registering the Plugin object */
 require_once 'Zend/Controller/Plugin/Acl.php';
 $front->registerPlugin(new Zend_Controller_Plugin_Acl($myAcl, $application->currentRole)); 
 
 /** Registering the Action Helper object */
 require_once 'Zend/Controller/Action/Helper/Acl.php';
 require_once 'Zend/Controller/Action/HelperBroker.php';
 Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_Acl()); 
 
 /** Dispatching the front controller */
 $front->dispatch();
И после регистрации помощника мы можем использовать его внутри любого контроллера.

Давайте предоставим права на изменение только владельцу или любому администратору.

Контроллер статей

 class ArticleController extends Zend_Controller_Action
 {
     protected $_acl;
     protected $_application;
 
     public function init()
     {
         /** Get our Action Helper */
         $this->_acl = $this->_helper->getHelper('acl'); 
 
         require_once 'Zend/Session/Namespace.php';
         $this->_application = new Zend_Session_Namespace('myApplication');
     } 
 
     .

public function editAction() { /** Load article by id */ $article = new Article($this->_request->id); /** Validate if the user is the owner or an Admin */ if (($article->author != $this->_application->loggedUser) && ($this->_application->currentRole != 'admin')) { $this->_acl->denyAccess(); } .

} }



Заключение

Некоторые охотники за мусором тратят свою жизнь, пытаясь найти недостающее звено (и умирают, пытаясь его найти), а некоторые ZFers состарятся, пытаясь заставить ACL правильно работать в их среде MVC. Надеемся, что приведенное выше предложение может оказаться одним из недостающих элементов в мире ACL+MVC. В заключение хочу дать рекомендацию.

Придерживайтесь принципа «Будь проще»: если вам совершенно не нужна динамическая загрузка ACL, то загрузить и настроить его вручную вовсе не грех; возможно, это лучший вариант действий в данной ситуации.

Чтобы узнать больше по этой теме, вы можете прочитать следующее: Интеграция Zend_Acl и MVC и небольшой пример реализации подхода, описанного в статье: Исходный код Кросспост: http://lobach.info/develop/zf/zend_acl-and-mvc-integration-part-2/ Теги: #acl #tutorial #Zend Framework #Zend Framework

Вместе с данным постом часто просматривают: