Symfony2 авторизация от корня

Автор: Aport Пятница, Январь 30th, 2015 Нет комментариев

Рубрика: Разное

Решил настроить Symfony так, чтобы фаервол работал в ней от корня, но при этом были доступны страницы авторизации.

Первым делом, хочется сказать, что сделать это нельзя с помощью обычных настроек в app/config/security.yml А с помощью наследования от Symfony\Bundle\FrameworkBundle\Controller\Controller у меня не получилось, да и не красиво это. А можно это сделать с помощью написания своего ControllerListener-а.

Давайте по шагам

1. Создаем файл по адресу src/Helper/ControllerListener.php

2. С содержимым:

<?php
namespace Helper;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
/**
 * класс проверяющий права доступа пользователя и в будущем может что-то еще
 * см. http://www.ricardclau.com/2011/08/kohana-style-before-and-after-methods-in-symfony2/
 * Class ControllerListener
 * @package Helper
 * @throws AccessDeniedException in case token is not valid
 */
class ControllerListener
{
    /**
     * This variable gets kernel container object
     *
     * @var ContainerInterface
     */
    protected $container;

    /**
     * This constructor method injects a Container object in order to have access to YML bundle configuration inside the listener
     *
     * @param ContainerInterface $container
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * This method handles kernelControllerEvent checking if token is valid
     *
     * @param FilterControllerEvent $event
     * @throws AccessDeniedException
     */
    public function onKernelController(FilterControllerEvent $event)
    {
        $controller = $event->getController();

        /**
         * $controller passed can be either a class or a Closure. This is not usual in Symfony2 but it may happien.
         * If it is a class, it comes in array format, so this works as @stof said
         * @see https://github.com/symfony/symfony/issues/1975
         */
        if (!is_array($controller)) {
            // not a object but a different kind of callable. Do nothing
            return;
        }

        /** @var Controller $controllerObject */
        $controllerObject = $controller[0];

        if($controllerObject instanceof Controller){

            // если это класс авторизации - проверять доступ не нужно
            if($controllerObject instanceof \Acme\AuthBundle\Controller\DefaultController){
                return ;
            }

            if(!$controllerObject->getUser()){// если пользователь авторизован
                throw new AccessDeniedException();// это вызов скажет фаерволу, что пользователь не авторизован
            }
        }
    }
}

3. Чтобы выше созданный класс заработал, добавим его как листенер в файл app/config/config.yml:

services:
    controller_listener:
        class: Helper\ControllerListener
        arguments: [@service_container]
        tags:
          - { name: kernel.event_listener, event: kernel.controller, method: onKernelController }

Готово.

p.s. если в результате Ваших настроек Вы получаете ошибку:

The controller must return a response (null given). Did you forget to add a return statement somewhere in your controller?

значит проблема вовсе не в бандле SensioFrameworkExtraBundle, как пишут некоторые. Если подебажить и подумать, оказывается, что в  фаерволе необходимо указывать form_login cо всеми параметрами типа login_path, check_path и т.п.

 

Источник: yapro.ru

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты