首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >父控制器重定向

父控制器重定向
EN

Stack Overflow用户
提问于 2017-06-22 15:12:20
回答 3查看 507关注 0票数 0

在我的ZF2 (2.4.5)项目中,我有一个主(父)控制器,它具有验证用户权限的功能,因此每个继承的控制器都可以轻松地访问它。然而,重定向有一个问题。我知道继承控制器的操作必须返回响应,但是是否有可能在父控制器中强制重定向?

父控制器

代码语言:javascript
运行
复制
<?php

namespace Application;

use Zend\Mvc\Controller\AbstractActionController;

class CoreController extends AbstractActionController{

    public function checkAccess($moduleName, $accessName){
        if($this->getAclService()->isAllowed($moduleName, $accessName)){
            self::redirect()->toRoute('access-denied');
        }
    }
}

继承控制器

代码语言:javascript
运行
复制
namespace Application\Controller;

use Application\CoreController;
use Zend\View\Model\ViewModel;

class InterfaceController extends CoreController{

    public function indexAction(){

        $this->checkAccess('Foo', 'Bar');

        return new ViewModel([

        ]);
    }
}

如果我在InterfaceController中调用了InterfaceController,而$this->getAclService()->isAllowed($moduleName, $accessName)CoreController中返回了false,那么我想要重定向用户立即路由'access-denied',而不完成InterfaceController::indexAction的其余部分。

重要:我想避免检查checkAccess返回的内容,我只是强制重定向。

提前感谢您的回复。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-10-19 13:40:55

好的,我使用全局异常处理程序完成了这个任务。

子控制器

代码语言:javascript
运行
复制
<?php

namespace Warehouse\Controller;

use Application\CoreController;
use Zend\View\Model\ViewModel;

class IndexController extends CoreController {

    public function getWarehouseDocumentAction() {
        parent::checkAccess('Warehouse', 'incoming-goods');

        return new ViewModel([
            'foo' => 'bar',
        ]);
    }

}

父控制器

代码语言:javascript
运行
复制
namespace Application;

use Application\Exception\InsufficientPermissionException;
use Zend\Mvc\Controller\AbstractActionController;

class CoreController extends AbstractActionController {

    public function checkAccess($moduleName, $accessName){
        if(!$this->getServiceLocator()->get(MyAcl::class)->isAllowed($moduleName, $accessName, $this->identity())){
            throw new InsufficientPermissionException('Access denied. Insufficient permission.');
        }
    }
}

Module.php

代码语言:javascript
运行
复制
<?php

namespace Application;

use Application\Exception\InsufficientPermissionException;
use Application\Monolog\Handler\DoctrineLogMessageHandler;
use Zend\Mvc\MvcEvent;

class Module {

    public function onBootstrap(MvcEvent $e) {

        $sharedEvents = $e->getApplication()->getEventManager()->getSharedManager();

        $sharedEvents->attach('Zend\Mvc\Application', 'dispatch.error', function (MvcEvent $event) {
            if (php_sapi_name() !== 'cli') {
                $exception = $event->getParam('exception');
                if ($exception instanceof InsufficientPermissionException) {
                    $target = $event->getTarget();
                    return $target->redirect()->toRoute('access-denied');
                }
            }
        });

    }
}

权限保存在数据库中。

票数 1
EN

Stack Overflow用户

发布于 2017-06-22 15:32:13

我说这是不可能的。调用代码InterfaceController::indexAction至少需要返回,这将启动重定向过程。

您可以通过让基本控制器设置重定向来稍微清理它,但是继承的控制器需要通过调用返回来停止脚本的执行。

基控制器

代码语言:javascript
运行
复制
use Zend\Mvc\Controller\AbstractActionController;

class CoreController extends AbstractActionController{

    public function checkAccess($moduleName, $accessName){
        if (!$this->getAclService()->isAllowed($moduleName, $accessName))) {
            self::redirect()->toRoute('access-denied');
            return false;
        } else {
            return true;
        }
    }
}

继承控制器

代码语言:javascript
运行
复制
use Application\CoreController;
use Zend\View\Model\ViewModel;

class InterfaceController extends CoreController{

    public function indexAction(){

        if (!$this->checkAccess('Foo', 'Bar')) {
            return;
        }

        return new ViewModel([

        ]);
    }
}

编辑

另外,在我们的公司中,我们对基本控制器的init()方法进行ACL检查,没有覆盖,因此可以在运行任何操作代码之前立即执行重定向。

编辑#2

我完全忘记了我们使用的init方法。如果你在寻找另一种解决方案,那就试一试。

基控制器

代码语言:javascript
运行
复制
use Zend\Mvc\Controller\AbstractActionController;

class CoreController extends AbstractActionController{

    public function init() {
        // bootstrap code...

        // This should redirect
        if (!$this->_isUserAuthorized()) {
            return;
        }

        // If the ACL check was OK then pass control to controllers
        return parent::init();
    }

    private function _isUserAuthorized() {
        // checks done here
        // return true if OK
        // else

       $this->_response->setRedirect($this->view->defaultUrl($redirect))->sendResponse();
       return false;
    }
}

继承控制器

代码语言:javascript
运行
复制
use Application\CoreController;
use Zend\View\Model\ViewModel;

class InterfaceController extends CoreController{

    public function indexAction(){

        // nothing to do here

        return new ViewModel([]);
    }
}
票数 0
EN

Stack Overflow用户

发布于 2017-06-23 22:05:23

您正在执行一个简单的302 http重定向到“访问拒绝”,因此您可以只呈现响应对象并停止php执行:

代码语言:javascript
运行
复制
public function checkAccess($moduleName, $accessName){
    if (!$this->getAclService()->isAllowed($moduleName, $accessName))) {
        self::redirect()->toRoute('access-denied');
        $this->getResponse()->send();
        exit;
    } else {
        return true;
    }
}

您可以简单地抛出一个异常:

代码语言:javascript
运行
复制
public function checkAccess($moduleName, $accessName){
    if (!$this->getAclService()->isAllowed($moduleName, $accessName))) {
        self::redirect()->toRoute('access-denied');
        throw new \Exception('access denied');
    } else {
        return true;
    }
}

异常将阻止进一步的代码执行,重定向将防止呈现异常错误页。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44703303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档