【问题标题】:ZF3 redirection after ACL authorization failedACL 授权失败后的 ZF3 重定向
【发布时间】:2017-01-16 19:10:25
【问题描述】:

我有一个带有 ACL 的新 ZF3 应用程序。现在,如果未经授权的访问,我需要重定向到错误页面(例如 403)。我认为最好的方法是触发一个事件,然后捕获它,但我失败了......

所有内容都在我的用户模块中,在 Module.php(摘录)中:

namespace User;

use Zend\Mvc\MvcEvent;
use Zend\Permissions\Acl\Acl;
use Zend\Stdlib\Response ;
use Zend\View\Model\ViewModel;
[...]

class Module implements ConfigProviderInterface
{
    [...]

    public function onBootstrap(MvcEvent $e)
    {
        // Set event to check ACL, then to handle unauthorized access
        $eventManager = $e->getApplication()->getEventManager();
        $eventManager->attach(MvcEvent::EVENT_ROUTE, array($this, 'checkProtectedRoutes'), 1);
        $eventManager->attach(MvcEvent::EVENT_DISPATCH_ERROR, array($this, 'dispatchError'), -999);
        // Init ACL
        $this->initAcl($e);
    }

    public function initAcl(MvcEvent $e)
    {
        [...]
    }

    public function checkProtectedRoutes(MvcEvent $e)
    {
        // My access logic working fine. return if OK
        [...]

        // if authorization failed
        $e->setError('ACL_ACCESS_DENIED') ;
        $e->setParam('route', $route);
        $e->getTarget()->getEventManager()->trigger(MvcEvent::EVENT_DISPATCH_ERROR, $e);
    }

    public function dispatchError(MvcEvent $e)
    {
        // Check error type
        $error = $e->getError();
        switch ($error) {
            case 'ACL_ACCESS_DENIED' :
                // What should I do here ?

                break;
            default:
                return ;
            break;
        }
        return false ;
    }
}

但是当我的事件被触发时,我的dispatchError()方法永远不会被调用,ZF3哭了:

可捕获的致命错误:传递给 Zend\Mvc\View\Http\RouteNotFoundStrategy::detectNotFoundError() 的参数 1 必须是 Zend\Mvc\MvcEvent 的实例,给定 Zend\EventManager\Event 的实例,在 /xxxxxxx/ 中调用vendor/zendframework/zend-eventmanager/src/EventManager.php 在第 271 行,并在第 135 行的 /xxxxxxxx/vendor/zendframework/zend-mvc/src/View/Http/RouteNotFoundStrategy.php 中定义

我哪里错了,我应该如何触发/捕捉这个事件?

【问题讨论】:

    标签: php zend-framework2 zend-framework3 zf3


    【解决方案1】:

    由于您使用的是 ZF3,我可能会建议您将 ACL 逻辑从引导程序中移出并放入中间件中。如果 ACL 说请求没问题,你调用 $next 最终到达控制器。如果不是,则将响应的状态设置为 403 并返回响应。查看 zend-mvc 上的扩展坞,因为他们有一个针对这个问题的食谱示例。

    https://docs.zendframework.com/zend-mvc/cookbook/middleware-in-listeners/

    【讨论】:

    • 在我看来,这个答案并没有完全回答我的问题,但是因为它为我提供了改进开发的指标,所以我会奖励它...... Tks
    【解决方案2】:

    即使它没有解决事件问题,这也是我解决问题的方法,直接在我的checkProtectedRoutes() 方法中返回响应:

    // Erreur 403
    $e->stopPropagation();
    
    $baseModel = new ViewModel();
    $baseModel->setTemplate('403');
    
    $resolver = new TemplateMapResolver();
    $resolver->setMap( ['403' =>  __DIR__ . '/../view/error/403.phtml']);
    
    // Render view
    $renderer = new PhpRenderer();
    $renderer->setResolver($resolver);
    $content = $renderer->render($baseModel);
    $response = $e->getResponse();
    $response->setStatusCode(403);
    $response->getHeaders()->addHeaderLine('Location', $e->getRequest()->getBaseUrl() . '/login');
    $response->setContent($content);
    return $response ;
    

    【讨论】:

      【解决方案3】:

      我也遇到了同样的问题。 函数checkProtectedRoutes(MvcEvent $e) 的错误触发器应使用triggerEvent 方法。

      //ACL Permission test        
      if ( ! $auth->hasPermission( $e ) ) {
          $e->setName(MvcEvent::EVENT_DISPATCH_ERROR);
          $e->setError('ACL_ACCESS_DENIED');            
          $target = $e->getTarget();
          $res = $target->getEventManager()->triggerEvent( $e );
          return $res->last();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-04
        • 1970-01-01
        • 1970-01-01
        • 2020-12-18
        • 1970-01-01
        • 2020-12-07
        • 2020-07-16
        • 2014-01-25
        相关资源
        最近更新 更多