控制器类上的 @Security 注释被操作方法覆盖 [英] @Security annotation on controller class being overridden by action method
问题描述
我有一个 Symfony2 控制器,如下所示:
I have a Symfony2 controller as follows:
/**
* @Security("is_granted('my_permission')")
*/
class MyController extends Controller
{
/**
* @Security("is_granted('another_permission')")
*/
public function myAction()
{
// ...
}
}
myAction()
方法上的 @Security
注释覆盖/忽略了 MyController 上的父
类.有没有办法让这些堆栈,以避免必须做:@Security
注释
It appears the @Security
annotation on the myAction()
method overrides/ignores the parent @Security
annotation on the MyController
class. Is there any way to make these stack, to avoid having to do:
/**
* @Security("is_granted('my_permission') and is_granted('another_permission')")
*/
public function myAction()
{
// ...
}
在控制器中的每个动作方法上?
on every action method in the controller?
推荐答案
似乎 myAction 方法上的 @Security 注释覆盖/忽略了 MyController 类上的父级 @Security 注释.
It appears the @Security annotation on the myAction method overrides/ignores the parent @Security annotation on the MyController class.
确实,Sensio\Bundle\FrameworkExtraBundle\Configuration\Security
注释不允许嵌套配置(参见 allowArray()
方法).因此,方法配置会覆盖 @Security
注释的类配置.
Indeed, Sensio\Bundle\FrameworkExtraBundle\Configuration\Security
annotation doesn't allows nested configuration (see allowArray()
method). So method configuration overrides class configuration for @Security
annotation.
有没有办法让这些堆栈...
Is there any way to make these stack...
不是以简单的方式,您需要创建三个类和一个技巧来不重新实现整个父代码:
Not in a simple way, you need create three class and one trick to not reimplement the whole parent code:
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
这个类允许您通过所有安全配置(类/方法)复合最终的安全表达式.
This class allow you compound the final security expression through all security configurations (class/method).
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
注释而不是标准注释.
Finally, just use your @AppBundle\Configuration\Security
annotation instead the standard one.
这篇关于控制器类上的 @Security 注释被操作方法覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!