为已定义的路由添加条件异常

时间:2014-03-13 13:58:29

标签: symfony exception routes

我想拒绝对数据库中标志设置为true的成员的已定义路由的访问权限。例如,我可以为每个动作添加一个起始条件,如:

    if ( $this->getUser()->HasPowers() ) {
        throw new AccessDeniedException;
    }

但是有太多的动作和不同的控制器匹配要被拒绝的路线。

因此,在考虑任何其他行动之前,我正在考虑创建一条新路线(重复),该路线将执行该动作(如果必须这样做,则拒绝)。有可能吗?

2 个答案:

答案 0 :(得分:1)

在过滤之前应该做的伎俩。请阅读文档:Before filters with the kernel.controller Event

如果你有很多路由/控制器,或者你不喜欢实现接口,你可以简单地为kernel.request事件实现事件监听器:

# app/config/config.yml
services:
    before_controller.listener:
        class: Acme\DemoBundle\EventListener\BeforeController
        calls:
            - [ setSecurityContext, [ "@security.context" ]]
            - [ setRouter, [ "@router" ]]
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

接下来,实现监听器:

# src\Acme\DemoBundle\EventListener;
namespace Acme\DemoBundle\EventListener;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\Security\Core\SecurityContext;

class BeforeController {
    protected $securityContext;

    protected $router;

    public function setRouter(Router $router){
        $this->router = $router;
    }

    public function setSecurityContext(SecurityContext $securityContext){
        $this->securityContext = $securityContext;
    }

    public function onKernelRequest(GetResponseEvent $event){
        if (!$this->securityContext->getToken()) {
            return;
        }

        $isUser = $this->securityContext->isGranted('ROLE_USER');

        if (!$isUser) {
            return;
        }

        $user = $this->securityContext->getToken()->getUser();

        if ($user->hasSomeFlag()) {
            $redirectUrl = $this->router->generate('some_route');
            $event->setResponse(new RedirectResponse($redirectUrl));
        }
    }
}

答案 1 :(得分:0)

我有同样的问题,但我不认为不同的路线是正确的解决方案。看看Matt Drollette提出的这个解决方案:

https://matt.drollette.com/2012/06/calling-a-method-before-every-controller-action-in-symfony2/

这对我来说非常合适。基本上,您创建一个控制器接口,在每个其他操作之前调用特定方法,然后在您需要检查用户是否具有Powers()的所有控制器中实现此接口。