【问题标题】:Zend-Framework how to detect not extisting action with zend_aclZend-Framework 如何使用 zend_acl 检测不存在的操作
【发布时间】:2010-11-11 08:37:46
【问题描述】:
$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 index 和操作 view
  • 但是当他输入 url /index/view2 时,它应该将他重定向到错误页面,因为操作 view2 不存在
  • 但是这个条件是他被允许查看动作视图。所以它不是将他重定向到错误页面,而是访问被拒绝

如何解决这个问题?

【问题讨论】:

标签: zend-framework action zend-acl


【解决方案1】:

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

【讨论】:

  • 我已经在下面发布了我的代码,我正在从前端控制器插件调用 acl。您能否提供一些代码如何使用 __call 方法 - 来自前端控制器插件
  • @tom:已更新。但我认为这不是要走的路(无论是解决问题还是“正确”的方式)。
  • 是的,__call 方法正是我想要的,谢谢
【解决方案2】:

我在前端控制器插件的预调度中调用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 );
    }           
}

【讨论】:

    【解决方案3】:

    我会通过抛出 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)
    }
    

    标准异常将照常处理。

    【讨论】:

    • 你误会了我,我知道如何重定向,但我不知道如何检测不存在的操作
    猜你喜欢
    • 2015-01-10
    • 2011-11-10
    • 2018-10-06
    • 2011-02-16
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    相关资源
    最近更新 更多