2016-09-08 4 views
4

У меня есть новое приложение ZF3 с ACL. Теперь мне нужно, в случае несанкционированного доступа, перенаправить на страницу с ошибкой (например, 403). Я думаю, что лучший способ это огонь событие, а затем поймать его, но я не смог ...Перенаправление ZF3 после авторизации ACL не удалось

Все в моем модуле пользователя, в 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 крик:

Catchable fatal error: Argument 1 passed to Zend\Mvc\View\Http\RouteNotFoundStrategy::detectNotFoundError() must be an instance of Zend\Mvc\MvcEvent, instance of Zend\EventManager\Event given, called in /xxxxxxx/vendor/zendframework/zend-eventmanager/src/EventManager.php on line 271 and defined in /xxxxxxxx/vendor/zendframework/zend-mvc/src/View/Http/RouteNotFoundStrategy.php on line 135

Где я не прав и как я должен вызвать/поймать это событие?

ответ

3

Поскольку вы используете ZF3, я мог бы предложить переместить логику ACL из бутстрапа и в промежуточное программное обеспечение. Если ACL говорит, что запрос в порядке, вы вызываете $ next, который в конечном итоге попадает на контроллер. Если это не так, вы устанавливаете статус ответа на 403 и возвращаете ответ. Проверьте доки на zend-mvc, поскольку у них есть пример поваренной книги для этой самой проблемы.

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

+0

Мне кажется, что этот ответ не полностью отвечает на мой вопрос, но поскольку он дает мне показатели для улучшения dev, я награжу его щедростью ... Tks –

0

Даже если это не решает проблему событий, это то, как я решил эту проблему, возвращая ответ непосредственно на мой 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 ; 
0

Я получил то же самое проблема. Ошибка при срабатывании функции 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(); 
}