Zend-Framework如何使用zend_acl检测未加载动作

时间:2010-11-11 08:37:47

标签: zend-framework action zend-acl

$this->add ( new Zend_Acl_Resource ( 'index' ) );
$this->addRole ( new Zend_Acl_Role ( 'guest' ) );
$this->allow('guest', 'index','view');

我在这种情况下遇到问题

if (! $this->_acl->isAllowed ( $role, $resource, $action )){ 
    ... redirect to access denied
}
  • 允许访客访问Contoller 索引和操作查看
  • 但是当他输入url / index / view2时,它应该将他重定向到错误页面,因为 view2 操作不存在
  • 但是这种情况表明他被允许参加行动。因此,它不会将他重定向到错误页面,而是拒绝访问

如何解决这个问题?

3 个答案:

答案 0 :(得分:3)

您可以检查acl中存在的资源(操作):

if(!$this->_acl->has($resource) || $this->_acl->isAllowed($role, $resource, $action))

其他人可以默认拒绝。如果您然后检查不存在的操作,则默认情况下acl将返回false 如果您只想检测是否从控制器调用了不存在的操作,则可以使用控制器的__call方法。

对于更具体的解决方案,您应该提供更多信息,例如您执行acl-check的位置,如何设置您的acl,....

捕获控制器中不存在的操作的示例:

My_Controller extends Zend_Controller_Action
{
    __call($method, $args)
    {
        throw new Exception("Action does not exist"); // This is done by default
        // Just do whatever you want to do in this function (like redirecting)
    }
}

无论如何,即使没有魔术功能,也可以使用ErrorhandlerPlugin完成。由于您只想重定向到错误页面,实际上只需要注意,acl检查不会抛出任何异常,因为找不到资源(或Action)。根据您的检查位置,您有几个可行性,但假设每个控制器都是一个资源,并且您所有添加它们,这应该不是问题。

答案 1 :(得分:1)

我在frontcontroller的frontcontroller插件中调用ACL

public function preDispatch(Zend_Controller_Request_Abstract $request) {
    if ($this->_auth->hasIdentity ()) {
        $rights = $this->_auth->getIdentity ()->rights;
        if ($rights == 2) {
            $role = 'admin';
        } elseif ($rights == 1) {
            $role = 'user';
        } else {
            $role = 'guest';
        }
    } else {
        $role = 'guest';
    }
    $controller = $request->controller;
    $action = $request->action;
    $module = $request->module;
    $resource = $controller;
    if ($this->_acl->has ( $resource )) {
        if (! $this->_acl->isAllowed ( $role, $resource, $action )) {
            if (! $this->_auth->hasIdentity ()) {
                //redirect to login
                $module = $this->_noauth ['module'];
                $controller = $this->_noauth ['controller'];
                $action = $this->_noauth ['action'];            
            } else {
                //redirect to access denied
                $module = $this->_noacl ['module'];
                $controller = $this->_noacl ['controller'];
                $action = $this->_noacl ['action'];
            }
            $request->setModuleName ( $module );
            $request->setControllerName ( $controller );
            $request->setActionName ( $action );
        }
    } else {
        //controller not found
        $module = ('default');
        $controller = ('error');
        $action = ('not-found');
        $request->setModuleName ( $module );
        $request->setControllerName ( $controller );
        $request->setActionName ( $action );
    }           
}

答案 2 :(得分:0)

我会通过抛出NotAllowed例外来做到这一点。

if (! $this->_acl->isAllowed ( $role, $resource, $action )){ 
    throw new YourNotAllowedException('some error message');
}

然后在错误控制器中我会处理这个异常:

if ($error->exception instanceof NotAllowed) {
   // manual forward setting request params 
   // (url remains the same, but user sees the login page)
}

标准例外将照常处理。