На Девзона появился вторая часть статьи об интеграции 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-
Любовь И Совы: Чем Хороша Ночная Смена
19 Oct, 24 -
Вконтакте Запускает Программу Bugbounty
19 Oct, 24