上控制器类@security注释由操作方法被重写(@Security annotation on c

2019-09-29 19:58发布

我有一个Symfony2的控制器如下:

/**
 * @Security("is_granted('my_permission')")
 */
class MyController extends Controller 
{
    /**
     * @Security("is_granted('another_permission')")
     */
    public function myAction() 
    {
        // ...
    }
}

它出现在@Security上注释myAction()方法覆盖/忽略父@Security上注释MyController类。 有没有什么办法让这些堆栈,以避免做:

/**
 * @Security("is_granted('my_permission') and is_granted('another_permission')")
 */
public function myAction() 
{
    // ...
}

在控制器的每一个动作的方法?

Answer 1:

它出现在myAction方法重写@security注解/忽略对类myController的父@security注释。

事实上, Sensio\Bundle\FrameworkExtraBundle\Configuration\Security标注没有允许嵌套配置(见allowArray()方法)。 所以方法配置将覆盖类配置@Security注解。

有没有什么办法让这些堆...

没有一个简单的方法,你需要创建三个类,并一招不重新实现整个父代码:

Security.php

namespace AppBundle\Configuration;

/**
 * @Annotation
 */
class Security extends \Sensio\Bundle\FrameworkExtraBundle\Configuration\Security
{
    public function getAliasName()
    {
        return 'app_security';
    }

    public function allowArray()
    {
        // allow nested configuration (class/method).
        return true;
    }
}

SecurityConfiguration.php

这个类允许你通过所有安全配置(类/方法)。化合物的最终安全表达。

namespace AppBundle\Configuration;

class SecurityConfiguration
{
    /**
     * @var Security[]
     */
    private $configurations;

    public function __construct(array $configurations)
    {
        $this->configurations = $configurations;
    }

    public function getExpression()
    {
        $expressions = [];
        foreach ($this->configurations as $configuration) {
            $expressions[] = $configuration->getExpression();
        }

        return implode(' and ', $expressions);
    }
}

SecurityListener.php

namespace AppBundle\EventListener;

use AppBundle\Configuration\SecurityConfiguration;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class SecurityListener extends \Sensio\Bundle\FrameworkExtraBundle\EventListener\SecurityListener
{
    public function onKernelController(FilterControllerEvent $event)
    {
        $request = $event->getRequest();
        if (!$configuration = $request->attributes->get('_app_security')) {
            return;
        }

        // trick to simulate one security configuration (all in one class/method).
        $request->attributes->set('_security', new SecurityConfiguration($configuration));

        parent::onKernelController($event);
    }

    public static function getSubscribedEvents()
    {
        // this listener must be called after Sensio\Bundle\FrameworkExtraBundle\EventListener\ControllerListener.
        return array(KernelEvents::CONTROLLER => array('onKernelController', -1));
    }
}

services.yml

services:
    app.security.listener:
        class: AppBundle\EventListener\SecurityListener
        parent: sensio_framework_extra.security.listener
        tags:
            - { name: kernel.event_subscriber }

最后,只需用@AppBundle\Configuration\Security注解来替代标准之一。



Answer 2:

这里是我的尝试:

使用,在app/config/security.yml ,这个角色层次:

role_hierarchy:
    ROLE_CLASS: ROLE_CLASS
    ROLE_METHOD: [ROLE_CLASS, ROLE_METHOD]

如果我有两个用户: user1ROLE_CLASSuser2ROLE_METHOD (这意味着该用户有两个角色),然后第一用户可以看到控制器内创建的所有页面,除了有额外限制的人。

控制器例如:

/**
 * @Security("is_granted('ROLE_CLASS')")
 */
class SomeController extends Controller
{
    /**
     * @Route("/page1", name="page1")
     * @Security("is_granted('ROLE_METHOD')")
     */
    public function page1()
    {
        return $this->render('default/page1.html.twig');
    }

    /**
     * @Route("/page2", name="page2")
     */
    public function page2()
    {
        return $this->render('default/page2.html.twig');
    }
}

所以,因为user1具有ROLE_CLASS ,他能看到的只是/page2 ,而不是/page1 ,他将获得403 Expression "is_granted('ROLE_METHOD')" denied access. 错误(dev的明显)。 在另一方面, user2 ,有ROLE_METHOD (和ROLE_CLASS ),他是能够看到这两个网页。



文章来源: @Security annotation on controller class being overridden by action method