ACL Ressource (контроллер) - PullRequest
       23

ACL Ressource (контроллер)

0 голосов
/ 13 сентября 2011

Я только что реализовал ACL в моей Zend Framework, которая уже использует Zend Auth.

Я хочу предоставить доступ к некоторым контроллерам и попробовал это так:

$roleGuest = new Zend_Acl_Role('guest');
$this->addRole($roleGuest);

$this->addRole(new Zend_Acl_Role('supplier'));
$this->addRole(new Zend_Acl_Role('admin'));

$this->add(new Zend_Acl_Resource('Articles'));
$this->add(new Zend_Acl_Resource('Index'));

$this->deny();

$this->allow('supplier', 'Articles');

$this->allow('admin', null);

Но пользователь,Кто является поставщиком (он действительно :)) не может видеть Статьи Контроллера.Что я делаю не так?

Спасибо за помощь.

BR frgtv10

Ответы [ 2 ]

0 голосов
/ 13 сентября 2011

Подход от пользователя 707795 хорош.Я создаю свои ресурсы с помощью Pike_Reflection_Resource, чтобы автоматически определять ваши ресурсы.Это еще не полностью задокументировано, но использование очень простое:

Вы загружаете последнюю версию библиотеки Pike http://code.google.com/p/php-pike/

Затем вы создаете класс ACL, расширяющий Zend_Acl:

<?php
class Application_Acl extends Zend_Acl
{

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->_addRoles();
        $this->_addResources();
        $this->_setAuthorization();
    }

    /**
     * Adds roles to ACL
     */
    protected function _addRoles()
    {
        /**
         * Get your roles from the application config here or the database like below (Doctrine2)
         */
//        $repository = $this->_em->getRepository('BestBuy\Entity\Usergroup');       

        $roles = array('guest', 'admin', 'moderator');

        foreach($roles as $role) {
            $this->addRole(new Zend_Acl_Role(strtolower($role)));            
        }               
    }

    /**
     * Adds resources to ACL
     * 
     * Here are resources added to the ACL. You don't have to do this manually 
     * because Pike_Reflection_Resource will search automaticly in your controller
     * directories to define which actions there are and adds every resource as:
     * modulename_controller_actionname all lowercase.
     */
    public function _addResources()
    {
        $resourceReflection = new Pike_Reflection_Resource();
        $resources = $resourceReflection->toFlatArray('default');

        foreach ($resources as $resource => $humanValue) {
            $this->addResource(new Zend_Acl_Resource($resource));
        }
    }

    /**
     * Sets authorization
     */
    public function _setAuthorization()
    {   

        //$permissions = $this->_em->getRepository('BestBuy\Entity\Permission')->findAll();
        /**
         * I retrieve my permissions here from the database but you could receive the
         * from the roles attribute too:
         */
        $resourceReflection = new Pike_Reflection_Resource();
        $resources = $resourceReflection->toArray('default');

        foreach ($resources as $moduleName => $controllers) {
            foreach($controllers as $controllerName=>$actions) {
                foreach($actions as $actionName=>$action) {

                    $resourceName = sprintf('%s_%s_%s',
                        strtolower($moduleName),
                        strtolower($controllerName),
                        strtolower($actionName)
                    );                    

                    if(isset($action['roles'])) {
                        foreach($action['roles'] as $role) {
                            if ($this->hasRole($role) && $this->has($resourceName)) {
                                $this->allow($role, $resourceName);
                            }                            
                        }
                    }
                }
            }
        }                     
    }
}
?>

Затем вы настраиваете плагин frontcontroller, как описано выше:

    <?php
class Application_Controller_Plugin_Authorization extends Zend_Controller_Plugin_Abstract
{
    /**
     * Request
     *
     * @var Zend_Controller_Request_Abstract
     */
    protected $_request;

    /**
     * ACL
     *
     * @var Buza_Acl
     */
    protected $_acl;

    /**
     * Called before Zend_Controller_Front enters its dispatch loop.
     *
     * @param  Zend_Controller_Request_Abstract $request
     * @return void
     */
    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)        
    {        
    $this->_request = $request;
    $this->_acl = new Application_Acl();

    Zend_Registry::set('acl', $this->_acl);

    $this->_checkAuthorization();
    }

    /**
     * Checks if the current user is authorized
     */
    protected function _checkAuthorization()
    {
    $allowed = false;
    $currentResource = sprintf('%s_%s_%s',
        strtolower($this->_request->getModuleName()),
        strtolower($this->_request->getControllerName()),
        strtolower($this->_request->getActionName())
    );

    if(Zend_Auth::getInstance()->hasIdentity()) {
        $user = Zend_Auth::getInstance()->getIdentity());

        $identityRole = strtolower($user->getRole()); //make sure you implement this function on your user class/identity!
    } else {
        $identityRole = 'guest';
    }

    if ($this->_acl->hasRole($identityRole) && $this->_acl->has($currentResource)) {
        if ($this->_acl->isAllowed($identityRole, $currentResource)) {
            $allowed = true;
        }           
    }        

    if ($allowed !== true) {                        
        throw new Zend_Controller_Exception('No permission', 403);            
    }        
    }

}
    ?>

Наконец, в вашем контроллере / действиях вы определяете свои права следующим образом:

<?php
class IndexController extends Zend_Controller_Action {
    /**
     * @human Some description for the permissions of this action
     * @roles guest|admin|moderator
     */
    public function indexAction() {
    }

    /**
     * @human Only for admins!
     * @roles admin
     */
    public function secretAction() {
    }
}
?>

Этот подходлучший и настроенный для небольших приложений.Для приложений, в которых вы хотите определить разрешенные действия в интерфейсе приложения, вы должны оставить тег ролей и получить разрешения для базы данных.

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

0 голосов
/ 13 сентября 2011

Я думаю, что лучшее решение - создать плагин и написать что-то вроде этого

    class Application_Controller_Plugin_AclManager extends Zend_Controller_Plugin_Abstract
{
   public function preDispatch(Zend_Controller_Request_Abstract $Request)
   {
      $AclManager = new Zend_Acl();

      $AclManager->addRole(new Zend_Acl_Role('Guest'));
      $AclManager->addRole(new Zend_Acl_Role('Supplier'), 'Guest');

      $AclManager->addResource(new Zend_Acl_Resource('controller1'));
      $AclManager->addResource(new Zend_Acl_Resource('controller2'));
      $AclManager->addResource(new Zend_Acl_Resource('controller3'));

      $AclManager->allow('Guest', 'controller1', 'index');
      $AclManager->allow('Supplier', 'controller2');
      $AclManager->allow('Supplier', 'controller3');

Это будет прекрасно работать.Кроме того, вы можете написать

if (! $AclManager->isAllowed(USER_ROLE, $Request->getControllerName(), $Request->getActionName()))
      {
         $this->getResponse()->setRedirect(SOME_URL_TO_REDIRECT);
      }
...