2017-01-04 51 views
1

被重寫我有一個Symfony2的控制器如下:@security註釋由動作方法

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

它出現在myAction()方法重寫@Security註解/忽略對MyController類的父@Security註釋。有沒有辦法讓這些堆棧,以避免做:

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

在控制器的每一個動作的方法?

回答

3

看來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註釋,而不是標準之一。

0

這裏是我的嘗試:

使用,在app/config/security.yml,這個角色層次:

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

如果我有兩個用戶:user1ROLE_CLASS,並user2ROLE_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'); 
    } 
} 

是因爲user1ROLE_CLASS,他能看到的只是/page2,但不/page1,因爲他將獲得403 Expression "is_granted('ROLE_METHOD')" denied access.錯誤(dev的明顯)。另一方面,user2,有ROLE_METHOD(和ROLE_CLASS),他能夠看到這兩個頁面。

相關問題