Конфликт на персонализирана анотация с @secure от jms/SecurityExtraBundle

Написах анотация, която хвърля AccesDeniedException, когато действието не се извиква от AJAX заявка (XMLHttpRequest).

Работи, но когато искам да използвам анотацията @Secure(roles="A") от JMS/SecurityExtraBundle, тя не работи, сякаш съм пропуснал персонализираното си изключение.

Контролер

namespace Mendrock\Bundle\SagaBundle\Controller;

use JMS\SecurityExtraBundle\Annotation\Secure;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Mendrock\Bundle\SagaBundle\Entity\Saison;
use Mendrock\Bundle\SagaBundle\Form\SaisonType;
use Mendrock\Bundle\ExtraBundle\Annotation\XmlHttpRequest;


/**
* @Route("/episodesAjax")
*/
class EpisodeController extends Controller {
    /**
     * @XmlHttpRequest()
     * @Secure(roles="ROLE_SUPER_ADMIN")
     * 
     * @Route("/saisonAdd", options={"expose"=true})
     * @Template()
     */
    public function saisonAddAction() {
        $entity = new Saison();
        $form = $this->createForm(new SaisonType(), $entity);

        return array(
            'entity' => $entity,
            'form' => $form->createView(),
        );
    }

Анотация

namespace Mendrock\Bundle\ExtraBundle\Annotation;

use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

/**
 * @Annotation
 */
class XmlHttpRequest 
{
    public $message = 'The action could be an XMLHttpRequest call.';

    public function checkRequest($event){
        if (!$event->getRequest()->isXmlHttpRequest()) {
            throw new AccessDeniedHttpException($this->message);
        }
    }

    public function execute($event){
        $this->checkRequest($event);
    }
}

Слушател

namespace Mendrock\Bundle\ExtraBundle\Listener;

use Doctrine\Common\Annotations\Reader;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Mendrock\Bundle\ExtraBundle\Annotation\XmlHttpRequest;

class EventListener {

    private $reader;

    public function __construct(Reader $reader) {
        $this->reader = $reader;
    }

    /**
     * This event will fire during any controller call
     */
    public function onKernelController(FilterControllerEvent $event) {

        if (!is_array($controller = $event->getController())) { 
            return;
        }
        $method = new \ReflectionMethod($controller[0], $controller[1]);

        foreach ($this->reader->getMethodAnnotations($method) as $configuration) {
            if ($configuration instanceof XmlHttpRequest) {
                $configuration->execute($event);
            }
        }
    }
}

Някаква идея защо не мога да използвам едновременно @Secure(...) и @XMLHttpRequest?

Редактиране:

услуги.yml

services:
    annotations.xmlhttprequest:
        class: Mendrock\Bundle\ExtraBundle\Listener\EventListener
        tags: [{name: kernel.event_listener, event: kernel.controller, method: onKernelController}]
        arguments: [@annotation_reader]

person manu    schedule 20.08.2012    source източник
comment
Здравейте, моля, включете и вашата конфигурация, за да заредите ControllerListener като услуга/слушател   -  person AdrienBrault    schedule 21.08.2012


Отговори (3)


Сблъсках се със същия проблем, когато исках да добавя свои собствени пояснения. Решението, използващо ClassUtils::getUserClass, няма да работи (използвайки Symfony 2.3, ако това има значение).

Тъй като използваме само анотацията @Secure от JMS\SecurityExtraBundle, накарах нашата кодова база да използва LswSecureControllerBundle вместо.

Този пакет предоставя само @Secure и не прави вуду трикове с вашите контролери.

person michel v    schedule 18.09.2013

Сблъсквам се със същия проблем след надграждане до Symfony 2.1.

Проблемът от моето разследване е, че JMS SecurityExtraBundle генерира прокси класове всеки път, когато използвате една от техните анотации. Проблемът с генерираните прокси класове е, че персонализираните анотации не се проксиират, поради което изглежда, че анотациите липсват.

Решението според автора е да се пренапише чрез AOP (осигурени съоръжения от JMSAopBundle) или да използвате ClassUtils::getUserClass.

person dteoh    schedule 14.12.2012
comment
И така, как можем да направим това? Трябва ли да направим друго прокси? Също така ще се опитам да разреша проблема си с aop парадигмата. - person manu; 14.12.2012
comment
Попитах автора на JMSSecurityExtraBundle и актуализирах отговора си с препратка към неговото решение. - person dteoh; 15.12.2012

Благодаря на suihock, че посочи това:

$class = \CG\Core\ClassUtils::getUserClass($controller[0]);
$method = new \ReflectionMethod($class, $controller[1]);
person coma    schedule 15.01.2013