Symfony:如何触发动态路由的自定义安全选民

时间:2016-03-15 13:15:05

标签: php symfony

我有以下设置:

  • 动态路由加载器,根据数据库中有关应用程序视图的信息生成路由并调用适当的控制器

  • 自定义安全选民,用于验证用户是否应该有权访问当前视图

我当然可以从适当的控制器中调用 is_granted 方法并且它可以工作。我想要做的是触发选民不是来自控制器内部(这需要在每个控制器中重复自己只有不同的视图ID),而是自动对路由加载器中生成的每个路径进行调整。这样我就不必对每条路径执行基本相同的标准验证 - 检查用户是否可以访问此视图,但要关注业务逻辑,这可能需要额外的要求来满足用户访问此路由(以及是控制器中的内容。

我正朝着路线生成方法中有一些参数的方向前进:

    $route = new Route($path, $defaults, $requirements);

    $routes->add($routeName, $route);

这将允许我为创建的路线触发is_granted,但有关参数的文档很少。

有谁知道如何将这种要求传递给用户,例如。对于创建的路线,要求用户 is_granted(' VIEW_1')

1 个答案:

答案 0 :(得分:2)

您可以将任何想要的内容添加到默认数组中,它们将被传递。例如:

cerad_game__project__game__update__by_scorer:
  path:  /project/{_project}/game/{_game}/update-by-scorer
  defaults:
    _role:       ROLE_SCORER_ADMIN
    _model:      cerad_game__project__game__update__by_scorer__model_factory
    _form:       cerad_game__project__game__update__by_scorer__form_factory
    _controller: cerad_game__project__game__update__by_scorer__controller:action
    _template: '@CeradGame/Project/Game/Update/ByScorer/GameUpdateByScorerTwigPage.html.twig'

然后,您将创建一个内核控制器侦听器,它将在解析控制器之后但在调用控制器操作方法之前调用。

class ModelEventListener extends ContainerAware implements EventSubscriberInterface {

public static function getSubscribedEvents()
{
    return array(
        KernelEvents::CONTROLLER => array(  
            array('onControllerRole',  self::ControllerRoleEventListenerPriority),
            array('onControllerModel', self::ControllerModelEventListenerPriority),
            array('onControllerForm',  self::ControllerFormEventListenerPriority),
        ),
        KernelEvents::VIEW => array(
            array('onView', self::ViewEventListenerPriority),
        ),
    );
}

public function onControllerRole(FilterControllerEvent $event)
{
    if (!$event->getRequest()->attributes->has('_role')) return;

    $role = $event->getRequest()->attributes->get('_role');

    $securityContext = $this->container->get('security.context');

    if (!$securityContext->isGranted($role))
    {
        // For public it redirects
        // For users we see the exception
        // die('access denied ' . $event->getRequest()->attributes->get('_route'));
        throw new AccessDeniedException(); 
    }
}

然后将其连线:

cerad_core__model_event_listener:
    class:  '%cerad_core__model_event_listener__class%'
    calls:
        - [setContainer, ['@service_container']]
    tags:
        - { name: kernel.event_subscriber }

此处记录:http://symfony.com/doc/current/cookbook/event_dispatcher/event_listener.html

请注意,我在此处注入了容器,而不仅仅是安全上下文。我需要其他方法的容器。它也是2.7代码。还没有把它更新到3.0。