Переадресация на другой контроллер / действие из module.php
Я пишу модуль для ACL
в ZF2
И я почти закончил с этим.
Когда я застрял, когда пользователь не авторизован для доступа к запрашиваемой странице, я хочу перенаправить пользователя на страницу, показывающую 403
сообщение.
Я пытался перенаправить пользователя на 403
но это обновляет URL
, так что теперь я пытаюсь переслать пользователя.
Все, что я хочу сделать, это от Module.php
, Я пробовал ниже код -
module.php
if (!$isAllowed) {
$e->getApplication()->getServiceManager()->get('ControllerPluginManager')->get('forward')->dispatch('acl');
}
Используя это я получил следующую ошибку -
Uncaught исключение "Zend\Mvc\Exception\DomainException" с сообщением "Для плагина Forward требуется контроллер, реализующий InjectApplicationEventInterface"
Я также пытался реализовать Acl
контроллер с InjectApplicationEventInterface
, Но вопрос остается тем же.
Можете ли вы объяснить, как Forward
другому Action
от Module.php
?
Дайте мне знать, если вам нужно больше деталей.
4 ответа
Что вы можете сделать, так это прослушать событие отправки. Вы можете обновить соответствие маршрута во время этого события, чтобы оно соответствовало паре контроллер / действие, определенной вами для рендеринга страницы 403.
В коде:
use MvcEvent;
class Module
{
public function onBootstrap($e)
{
$app = $e->getApplication();
$acl = $app->getServiceManager()->get('ACL'); // get your ACL here
if (!$acl->isAllowed()) {
$em = $app->getEventManager();
$em->attach(MvcEvent::EVENT_DISPATCH, function($e) {
$routeMatch = $e->getRouteMatch();
$routeMatch->setParam('controller', 'my-403-controller');
$routeMatch->setParam('action', 'my-403-action');
}, 1000);
}
}
}
Пересылка - это шаблон для отправки контроллера, когда другой контроллер уже отправлен. Это не ваш случай, как я прочитал из вашего вопроса. Так что не используйте плагин forward, но измените соответствие маршрута перед его отправкой.
Вы не можете забыть, но перенаправить на свою страницу 403 следующим образом:
if (!$acl->isAllowed()) {
$response = $e->getResponse();
$response->getHeaders()->addHeaderLine('Location', $e->getRequest()->getBaseUrl() . '/403page');
$response->setStatusCode(403);
}
Я думаю, что если вы хотите отправить пользователю информацию о том, что он находится в зоне ограниченного доступа без обновления URL, вам необходимо:
- Измените макет, который показывает ограниченную область сообщения.
- Оставьте оригинальный макет и просто переключите шаблоны для вашего действия, чтобы оно показывало сообщение с ограниченным доступом.
После одного из этих действий вы просто меняете Response на 403. Если это то, что вы хотите, это просто сделать. Для любого действия в вашем контроллере вы хотите отправить статус 403 просто используйте:
$viewModel->setTemplate('partial/noRights');
$this->getResponse()->setStatusCode('403');
return $viewModel;
или если вы хотите изменить макет на свой:
$this->layout('layout/custom');
$this->getResponse()->setStatusCode('403');
return $viewModel;
Конечно, вы можете сделать это в разделе начальной загрузки вашего модуля, добавив прослушиватель на event_dispatch и там проверить, если $acl->isAllowed() после этого внесет изменения, которые я написал выше. Пример:
public function onBootstrap(MvcEvent $e)
{
$app = $e->getApplication();
$acl = $app->getServiceManager()->get('ACL'); // get your ACL here
if (!$acl->isAllowed()) {
$eventManager = $app->getEventManager();
$sharedEventManager = $eventManager->getSharedManager();
$sharedEventManager->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH, function($e) {
$controller = $e->getTarget(); //controller`s action which triggered event_dispatch
$controller->getResponse()->setStatusCode('403');
$controller->layout('layout/custom');
}, 1000);
}
}
Когда я реализовал ACL, я создал свой собственный модуль AUTH для авторизации и аутентификации.
В этом модуле я создал плагин ACL.. что-то вроде ниже
//Module.php
/**
* This method is called once the MVC bootstrapping is complete
*
* @param \Zend\EventManager\EventInterface $e
*/
public function onBootstrap(Event $e)
{
$services = $e->getApplication()->getServiceManager();
$eventManager = $e->getApplication()->getEventManager();
$eventManager->attach('dispatch', array($this, 'loadConfiguration'), 101);
}
/**
*
* @param \Zend\Mvc\MvcEvent $e
*/
public function loadConfiguration(MvcEvent $e)
{
$e->getApplication()->getServiceManager()
->get('ControllerPluginManager')->get('AclPlugin')
->checkAcl($e); //Auth/src/Auth/Controller/AclPlugin
}
// Auth / SRC /Auth/Controller/AclPlugin
namespace Auth\Controller\Plugin;
/**
* load libraries here
*/
class AclPlugin extends AbstractPlugin implements ServiceManagerAwareInterface
{
/*
* @var Doctrine\ORM\EntityManager
*/
protected $em;
protected $sm;
/**
* @param Doctrine\ORM\EntityManager $em
* @return string
*/
public function checkAcl($e)
{
$matches = $e->getRouteMatch();
$controller = $matches->getParam('controller');
$action = $matches->getParam('action', 'index');
if ($acl->isAllowed($role, $resource, $permission)) {
return;
} else {
$matches->setParam('controller', 'Auth\Controller\User'); // redirect
$matches->setParam('action', 'accessdenied');
return;
}
}
/// rest of the code here
}