我有一个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()
{
// ...
}
控制器中的每个操作方法?
答案 0 :(得分:2)
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
注释而不是标准注释。
答案 1 :(得分:0)
这是我的尝试:
在sp
中使用此角色层次结构:
app/config/security.yml
如果我有两个用户:role_hierarchy:
ROLE_CLASS: ROLE_CLASS
ROLE_METHOD: [ROLE_CLASS, ROLE_METHOD]
user1
,ROLE_CLASS
user2
(这意味着此用户同时拥有两个角色),那么第一个用户就可以看到控制器内创建的所有页面,除了那些有其他限制的页面。
控制器示例:
ROLE_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
,因为他会收到403 /page1
错误(显然是为了开发)。
另一方面,Expression "is_granted('ROLE_METHOD')" denied access.
,user2
(和ROLE_METHOD
),他能够看到两个页面。