Пользователь
0,0
рейтинг
12 июля 2008 в 15:31

Разработка → Интеграция Zend_Acl и MVC. Часть 1 (простейшее использование) перевод

Итак, что не так с Zend_Acl и текущей реализацией MVC в Zend Framework? Ничего неправильного нет, просто не слишком очевидно для разработчиков, как достичь оптимальной интеграции между этими двумя важными частями фреймворка.

Во-первых, эта статья основана на следующем предложении (link), в настоящий момент находящемся в стадии Ожидания рекомендации.
Ну, как это работает? Существуют два основных компонента в этом предложении:
  1. Плагин фронт-контроллера (Front Controller Plugin): этот компонент решает, имеет ли доступ текущий пользователь к открываемой странице.
  2. Помощник действия (Action Helper): Этот компонент позволяет проверить, имеет ли текущий пользователь доступ внутрь контроллера.

Опираясь на эти два компонента, давайте попробуем их на примере. Давайте будем говорить о сайте, подобном DevZone.
Нам потребуется контроллер для управления пользователями и еще один контроллер для управления статьями, так же 3 типа пользователей (ролей): одну для гостей, одну для авторов статей и еще одну для утверждения статей. Итого, мы имеем:

Ресурсы:
  1. Контроллер пользователей.
  2. Контроллер статей.

Роли:
  1. Гость (Guest).
  2. Автор (Writer).
  3. Администратор (Admin).

Настройка компонента Zend_Acl


После определения того, что нам нужно сделать, следующим шагом будет создание экземпляра Zend_Acl, отражающего нашу модель.
/** Creating the ACL object */
require_once 'Zend/Acl.php';
$myAcl = new 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';
$myAcl->add(new Zend_Acl_Resource('user'))
      ->add(new Zend_Acl_Resource('article'));

Создание привилегий


Теперь мы добавили роли и ресурсы в наш экземпляр Zend_Acl, пора объяснить, какие действия должны быть доступны для каких ролей.
  1. Гости не могут редактировать, добавлять и публиковать статьи.
  2. Авторы не могут публиковать статьи.
  3. Администраторы имеют полный доступ.

/** Creating permissions */
$myAcl->allow('guest', 'user')
      ->deny('guest', 'article')
      ->allow('guest', 'article', 'view')
      ->allow('writer', 'article', array('add', 'edit'))
      ->allow('admin', 'article', 'approve');

Создание страницы, отображаемой при отсутствии доступа


Нам нужно будет создать представление (view) и действие (action) на которое мы переадресуем всех пользователей, у которых недостаточно привилегий. Во-первых, мы создадим новое действие в нашем контроллере ошибок:
class ErrorController extends Zend_Controller_Action
{
    ....

    public function deniedAction()
    {
    }

    ....
}

Затем мы создадим наш файл представления (/application/views/scripts/error/denied.phtml) с некоторым предупреждающим сообщением:
<h1>Error</h1>
<h2>Access denied</h2>
<p>You are trying to access an area which you have not allowed.</p>

Завершение настройки


Хорошо, мы настроили наш экземпляр Zend_Acl. Следующий шаг — регистрация плагина контроллера. Это важная часть берет созданный нами экземпляр Zend_Acl и проверяет, доступна ли текущая страница пользователю.
/** 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'; 
$aclPlugin = new Zend_Controller_Plugin_Acl($myAcl);
$aclPlugin->setRoleName($currentUserRole);

$front->registerPlugin(new Zend_Controller_Plugin_Acl($acl, 'guest')); 

/** Dispatching the front controller */ 
$front->dispatch(); 

После завершения настройки, как только пользователь войдет в наше приложение, в зависимости от его/её роли будет либо отображена запрошенная страница, либо страница с сообщением о запрете доступа.

Для более подробного ознакомления с темой вы можете почитать следующее:
Zend_Acl & MVC Integration
и небольшой пример:
Source Code

Crosspost: http://lobach.info/develop/zf/zend_acl-and-mvc-integration-part-i/
Перевод: Aldemar Bernal
Лобач Олег @bladeofsteel
карма
18,9
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (17)

  • 0
    текст по компактнее сделайте - читать не удобно
    • +1
      так лучше?
      что-то не нашел как код прилично отформатировать :(
      • 0
        лучше)
        поиграйтесь с автоматическим форматированием. оно <br> вставляет везде где ни попадя
        • +1
          ну вот, расставил руками
          , вроде стало боле-мене терпимо. или еще где чего подправить?
  • +1
    Как я понимаю это перевод вот этого
    http://devzone.zend.com/article/3509-Zen…
    Вообще, в целом, это уже обмусоленно довольно сильно, и многие подобное решение юзют давно.
    Однако, для навичков полезно. Так что за перевод вам +
    • +1
      Спасибо.
      Это действительно перевод статьи с ДевЗоны (ссылка и автор есть в свойствах хабратопика)
  • 0
    Статья крайне не применима в реальных приложениях, т.к. количество ресурсов, права на которые нужно разрешать в большинстве приложений гораздо больше, чем в статье. Обычно ресурсом является не "news", а "news №3", права для которой нужно разрешать. О параметризации ресурсов идентификаторами здесь ничего не сказано.

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

      Реализовать "принадлежность" статьи кокретному автору тут нет возможности
      В исходниках есть реализация этого, но, правда, без ACL, простой проверкой равенства автора статьи текущему пользователю
      • 0
        Там предлагается механизм assert'ов, для определения применимости правила, но способа доставить какой-то контекст к assert'у нету ... только Zend_Registry, а это слишком неправильно
        • 0
          Я имел в виду вот этот участок NewsController:

          public function editAction()
          {
          $id = $this->_request->getParam('id');

          /** Load news by id */
          require_once 'News.php';
          $news = new News($id);

          /** Loading the user logged */
          require_once 'Zend/Session/Namespace.php';
          $myApp = new Zend_Session_Namespace('myApplication');

          if ($news->author != $myApp->loggedUser) {
          $this->_acl->denyAccess();
          }

          $this->view->id = $id;
          }
    • 0
      перевел вторую часть, в которой автор приближает свое предложение к реальности - http://habrahabr.ru/blog/webdev/46731.ht…
  • 0
    думаю, этот код требует пояснения:
    $aclPlugin = new Zend_Controller_Plugin_Acl($myAcl);
    $aclPlugin->setRoleName($currentUserRole);

    $front->registerPlugin(new Zend_Controller_Plugin_Acl($acl, 'guest'));

    насколько я понял, то здесь неувязка. должно быть либо:
    // создаем плагин
    $aclPlugin = new Zend_Controller_Plugin_Acl( $myAcl);
    $aclPlugin->setRoleName( $currentUserRole);

    // регистрируем его
    $front->registerPlugin( $aclPlugin);

    либо:
    // создаем плагин при регистрации
    $front->registerPlugin( new Zend_Controller_Plugin_Acl( $acl, 'guest')); // вместо 'guest' по логике должна быть $currentUserRole

    поправьте, если я не прав.
    • 0
      Да, вы правы. Если посмотреть на вторую часть статьи, то будет видно, что используется последний предложенный Вами вариант (только в место «гостя» используется текущая роль пользователя).

      Спасибо за ценное замечание.
  • 0
    Опечатка: Помощник действия (Action Helper): Этот компонент позволяет проверить, имеет ли текущий пользователь доступ внутрь контроллера.

    Наскольк я понял, подразумевается «внутри контроллера».
    • 0
      Имеется в виду: «Имеет ли пользователь доступ к запрошенному действию (action) контроллера (controller)».
      • 0
        Посмотрите вот здесь: framework.zend.com/wiki/pages/viewpage.action? pageId=39025 (последняя вкладка 8. Use Cases) — helper используется внутри контроллера, в данном примере — для перенаправления на страницу «Недостаточно прав доступа».
        • 0
          Ну, помощник действия априори используется внутри действия.

          На мой взгляд, противоречия между «внутрь» и «внутри» нет. Фразу, вызвавшую Ваше замечание можно переписать так: помощник действия позволяет проверить в вызванном действии имеет ли пользователь доступ к нему или нет.

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