控制器类上的@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屋!