ACL资源(控制器)

时间:2011-09-13 15:54:14

标签: zend-framework zend-acl

我刚刚在我的Zend Framework中实现了ACL,它已经使用了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 :(得分:0)

我认为最好的解决方案是创建一个插件并编写类似这样的内容

    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);
      }

答案 1 :(得分:0)

user707795的方法很好。我使用Pike_Reflection_Resource构建我的资源以自动定义您的资源。它尚未完整记录,但使用非常简单:

您下载最新版本的Pike库 http://code.google.com/p/php-pike/

然后创建一个扩展Zend_Acl的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);
                            }                            
                        }
                    }
                }
            }
        }                     
    }
}
?>

然后你设置一个类似于上面的前控制器插件:

    <?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() {
    }
}
?>

这种方法是小型应用程序的最佳选择。对于要在应用程序界面中定义允许操作的应用程序,应该保留roles标记并获取数据库的权限。

请注意,以下代码未经过测试,但经过一些审核后,它可以正常运行,您可以在代码中控制您的权限。