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

Решил настроить 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 и т.п.

Оцени публикацию:
  • 2,5
Оценили человек: 2
Теги : symfony, base controller, check role in all controllers, security from root, is_granted for all controllers

Похожие статьи:

Справочники и учебники:


Комментарии посетителей:
  • > Первым делом, хочется сказать, что сделать это нельзя с помощью обычных настроек в app/config/security.yml

    #app/config/security.yml
    security:
       role_hierarchy:
           ROLE_ADMIN:       [ROLE_USER]
           ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH, ROLE_HIDE]
       # ...
       firewalls:
            main:
               pattern: ^/
               # ...
       # ...
       access_control:
           # для тулбара в дев-режиме
           - { path: /_wdt/.*, role: IS_AUTHENTICATED_ANONYMOUSLY }
           - { path: /_profiler/.*, role: IS_AUTHENTICATED_ANONYMOUSLY }
           # для авторизации/регистрации
           - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
           - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
           - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
           # админка
           - { path: ^/admin/, role: ROLE_ADMIN }
           # авторизация обязательна от корня
           - { path: ^/, role: ROLE_USER }
    21 февраля 2015, 22:52 коммент полезен : 0 # Futuster
Предложения и пожелания:
Ваше имя:
Ваш E-mail:
Сколько будет Οдин + Τри
Главная
X

Новые заметки:

Про что мы забываем когда делаем оценку задачи по времени

Список вопросов для собеседования разработчика по телефону

Symfony2 авторизация без Doctrine2 для чайника

Phpstorm7 LiveEdit

Жесткий хабр или не хабр, тогда кто?

Яндекс.Деньги мошенничество

Как узнать какие страницы в поиске яндекса или это секрет

Последние комменты:

Yapro CMS:

Здравствуйте, Гость | Войти | Регистрация | Карта сайта | RSS ленты | Ошибка в тексте? Выделите её мышкой и нажмите: Ctrl + Enter

youtube.com/watch?v=7hFivbgIEqk

При полном или частичном использовании материалов данного сайта, ссылка на сайт "yapro.ru" обязательна как на источник информации.
Автоматический импорт материалов и информации с сайта запрещен.
Copyrights © 2007 - 2018 YaPro.Ru

Главная » Веб-мастеру » PHP »