0
$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不存在
  • 但是这个条件说他被允许 olny 用于行动视图。所以它不是将他重定向到错误页面,而是访问被拒绝

如何解决这个问题?

4

3 回答 3

3

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

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

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

对于更具体的解决方案,您应该提供更多信息,例如执行 acl 检查的位置、如何设置 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 检查不会因为找不到资源(或操作)而引发任何异常。根据您进行检查的位置,您有多种可能性来执行此操作,但假设每个控制器都是一个资源并且您都添加了它们,这应该不是问题。

于 2010-11-11T11:40:14.100 回答
1

我在前端控制器插件的预调度中调用 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 );
    }           
}
于 2010-11-13T08:25:47.653 回答
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)
}

标准异常将照常处理。

于 2010-11-11T17:17:13.190 回答