如何在Zend_Acl中允许不存在的权限?

时间:2013-03-22 15:02:09

标签: php zend-framework acl privileges blacklist

我正在使用ZF 1.12.2,我想为我的Zend_Acl权限创建一个黑名单,因为我的限制少于允许。我的ACL资源名称基于我的控制器名称和我的控制器操作名称上的权限。

现在,我否认这样的特权:

$acl->deny('user', null, 'User::login');

当我向我的用户控制器添加操作时,我希望隐式地授予用户角色访问权限,除非我明确拒绝它们。因此,如果我在用户控制器上添加编辑操作,则不必执行此操作:

$acl->allow('user', null, 'User::edit');

默认情况下,如果权限不存在,Zend_Acl::isAllowed将返回false。除非在调用父类之前将其子类化并存储,否则很难知道添加了哪些特权。我一直试图破译Zend_Acl::$_rules,因为我认为它符合我的需要,我可以避免继承。允许不存在的权限可以传递Zend_Acl::isAllowed吗?

更新:现在,我的工作子类方法My_Acl::isAllowed如下所示。 My_Acl::__construct接受一个数组配置,该数组配置包含要添加的嵌套特权/资源的角色。

public function isAllowed($role = null, $resource = null, $privilege = null)
{
    if (null !== $resource) {
        if (is_string($resource)) {
            $resource_id = $resource;
        } else {
            $resource_id = $resource->getResourceId();
        }

        if (!in_array($resource_id, array_keys($this->_resources))) {
            return true;
        }
    }

    if (null !== $privilege) {
        if (!in_array($privilege, array_keys($this->_privileges))) {
            return true;
        }
    }

    return parent::isAllowed($role, $resource, $privilege);
}

2 个答案:

答案 0 :(得分:0)

我不是ACL的专家,但据我所知,您可以allow()使用所有内容,然后根据需要使用deny()

//user can do all, by not specifying resources or privileges, all is allowed
$acl->allow('user');

//explicitly deny specific resources and privileges
$acl->deny('user', null, 'User::login');

请注意所应用的任何继承,因为这可能会导致意外行为。

希望这有帮助。

答案 1 :(得分:0)

您的isAllowed方法中有太多检查会使事情变得复杂

如果你没有使用模块化方法(HMVC),你应该使用isAllowed(role, resource, privilege)的第二个参数,可以使用controller作为第二个参数,并将action作为第三个参数:$acl->allow('user', 'user', 'edit');

如果您遵循此方法,则需要将控制器添加为资源

//user controller as resource.
$this->add(new Zend_Acl_Resource('user'));   

定义任意资源:nullresources

// any resource
$this->add(new Zend_Acl_Resource('nullresources'));       

$this->addRole(new Zend_Acl_Role('guest')); // guest role - no login (it's good to have something like this)

$this->allow('guest', 'nullresources');

如果添加任意资源:nullresources,您可以跳过isAllowed中的一些步骤。

  /**
   *
   * @param string $role
   * @param string $resource (module name)
   * @param String $privilege (controller name: action name)
   * @return Boolean
   */
  public function isAllowed($role = null, $resource = null, $privilege = null)
  {
      /**
       *  by default, undefined resources are allowed to all
       */
      if (!$this->has($resource)) {
          $resource = 'nullresources';
      }
      return parent::isAllowed($role, $resource, $privilege);
  }

如果您遵循这种方法,您应该能够以这种方式使用它:

$acl->allow('user', 'user');
$acl->deny('user', 'user', 'login');

修改

您还需要更改您正在进行检查的位置,例如,如果您使用插件,则可能是引导程序或某些插件,这是一个示例类

<?php 
class My_Acl_AccessCheck extends Zend_Controller_Plugin_Abstract
{
    private $_acl = null;

    public function __construct(Zend_Acl $acl)
    {
        $this->_acl = $acl;
    }

    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {            
        /**
         * get controller name
         * @var String $controller
         */
        $controller = $request->getControllerName();
        /**
         * get action name
         * @var String $action
         */
        $action = $request->getActionName();
        /**
         * getting the role from the registry and defining some
         * role for the null character as guest makes authentication more flexible
         * if the roles is not allowed to use the resource then the user is
         * redirected to action notAllowed of controller user
         *
         * Parameter passed for isAllowed: role, ControllerName, ActionName             
         */
        if(!$this->_acl->isAllowed(Zend_Registry::get('role'), $controller, $action))
        {
            $request->setModuleName('default')
                    ->setControllerName('user')
                    ->setActionName('notAllowed');
        }        

    }
}

bootstrap

    $this->_acl = new My_Acl();
    $frontController = Zend_Controller_Front::getInstance();
    $frontController->registerPlugin(new My_Acl_AccessCheck($this->_acl));