Перенаправление с существующего маршрута на новый

Я пытаюсь перенаправить, если пользователь не вошел в систему (работает с FOSUser и SonataAdmin) и вызывает либо http://domain.com/app_dev.php (dev), либо http://domain.com (prod), то я хочу в обоих случаях перенаправить на /login, поэтому я написал эту конфигурацию в app/routing.yml:

root:
    path: /
    defaults:
        _controller: FrameworkBundle:Redirect:urlRedirect
        path: /login
        permanent: true

Это работает, но у меня проблема, так как у меня есть это в контроллере:

/**
 * @param Request $request
 *
 * @return array
 * @Route("/", name="brand")
 * @Method("GET")
 * @Template()
 */
public function indexAction(Request $request)
{
    ....
}

Затем, когда я пытаюсь вызвать маршрут brand, например, используя ссылку типа: http://domain.com/app_dev.php/?email=7x-xRFClkjw (dev) или http://domain.com/?email=7x-xRFClkjw (prod), меня перенаправляют на /login. Моя лучшая идея - изменить мой код на это:

/**
 * @param Request $request
 *
 * @return array
 * @Route("/bp", name="brand")
 * @Method("GET")
 * @Template()
 */
public function indexAction(Request $request)
{
    ....
}

А затем перенаправить с помощью маршрута на новый /bp вместо / для этой функции (главным образом это связано с тем, что у пользователей уже есть тонны электронных писем, в которых есть ссылки, как ранее опубликованные, и я не могу это изменить). Но я понятия не имею, как написать это правило в routing.yml, потому что если бы я написал это:

bp:
    path: /
    defaults:
        _controller: FrameworkBundle:Redirect:redirect
        route: brand
        permanent: true

Я закончу с циклом перенаправления. Я также мог бы изменить способ настройки маршрута по умолчанию к /login, но я просто не могу найти нужную документацию. Основная идея этого поста — настроить маршрут по умолчанию для /. Может ли кто-нибудь помочь мне в этом?

В качестве дополнительной информации это часть моего файла security.yml:

firewalls:
    ...

    admin_area:
        pattern: ^/
        anonymous: ~
        form_login:
            provider: fos_userbundle
            csrf_provider: form.csrf_provider

            # the user is redirected here when they need to log in
            login_path: /login

            # submit the login form here
            check_path: /login_check

            # login success redirecting options (read further below)
            always_use_default_target_path: true
            default_target_path: /admin/dashboard
            target_path_parameter: _target_path
            use_referer: false
            failure_path: /admin/dashboard
            failure_forward: false
        logout:
            path:   /logout

ОБНОВЛЕНИЕ

На самом деле код от @emmanuel-hdz-díaz дает мне еще одну идею, и мне не нужно создавать прослушиватель ядра или добавлять много кода, просто сделав это на моем контроллере:

if ($request->query->get('email')) {
    ...
} else {
    return $this->redirect($this->generateUrl('sonata_user_admin_security_login'));
}

Мне удалось перенаправить пользователя на маршрут /login.


person ReynierPM    schedule 29.08.2015    source источник


Ответы (3)


Бросаем специальное исключение, ловим его в событии kernel.request, оттуда перенаправляем. Вы должны создать собственное исключение, в котором вы можете сохранить свой маршрут, например:

class RouteException extends \Exception{
    protected $route;

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

    public function getRoute() { return $this->route; }
}

Теперь создайте прослушиватель, который будет генерировать RedirectResponse при обнаружении этого исключения, например:

class RedirectExceptionListener{
  protected $router;

  public function __construct(RouterInterface $router){
    $this->router;
  }

  public function onException(GetResponseForExceptionEvent $event){

    $e = $event->getException();

    if($e instanceof RouteException){

      $url = $this->router->generate($e->getRoute());

      $event->setResponse(
        new RedirectResponse($url);
      );
    }
  }
}

# the service definition
your_listener:
    class: RedirectExceptionListener
    arguments:
        - @router
    tags:
        - { name: kernel.event_listener, event: kernel.exception, method: onKernelException }

Примечание: вы должны use использовать пространства имен для используемых классов.
Это в основном то, что вы можете сделать для перенаправления из любого места в вашем приложении, хотя это выглядит как вонючее использование исключений, поэтому создайте службу Redirecter с методом redirect($route), который генерирует исключение для вас, поэтому вызывающая служба не будет знать, как выполняется перенаправление. Redirecter может создать исключение или сделать что-либо необходимое для перенаправления на заданный маршрут.
Для дополнительную информацию о прослушивателях событий см. в разделе прослушиватели событий.

Обновление: именно так symfony перенаправляет вас на ваш login_path, когда вы не авторизованы, см. ExceptionListener

person user2268997    schedule 01.09.2015
comment
Отлично, я почти все понял, но где мне установить маршрут? Я имею в виду, что я вижу, что слушатель перенаправляется, но куда? - person ReynierPM; 02.09.2015
comment
Вы устанавливаете маршрут в исключении, смотрите конструктор исключения, вот где вы передаете маршрут. - person user2268997; 02.09.2015

Не уверен, что понял, но вы хотите ограничить доступ ко всему сайту? В этом случае просто измените настройки безопасности, никогда не добавляйте перенаправление для входа в систему, потому что оно всегда перенаправляет на вход, даже если вы вошли в систему. Вот простой пример конфигурации:

security:
    firewalls:
        main:
            pattern: ^/
            anonymous: true

access_control:
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/, role: ROLE_USER }
person malcolm    schedule 29.08.2015
comment
Нет, вы меня совсем не поняли. Доступ ограничен, если кто-либо попытается использовать URL-адрес /, например, http://domain.com/app_dev.php (для dev) или http://domain.com (для prod), тогда я смогу перенаправить на /login. Прямо сейчас у меня есть маршрут по коду, перекрывающему этот /, как вы можете видеть в основном посте, и я объясняю там свою идею. Мне нужны другие, так как я еще не могу это исправить - person ReynierPM; 31.08.2015
comment
В комментарии выше вы сказали: мне нужно одинаковое поведение перенаправления во всем приложении - это именно то, что нужно, перенаправить пользователя на страницу входа, если пользователь не зарегистрирован. - person malcolm; 31.08.2015

Попробуй это:

В вашем контроллере внутри yourAction():

//

$usr = $this->get('security.context')->getToken()->getUser();

if( $usr == 'anon.' )
{
return $this->redirect($this>generateUrl('sonata_user_admin_security_login'));
}

//

person Emmanuel HD    schedule 29.08.2015
comment
Это будет работать только для этого контроллера, и я не хочу, чтобы мне нужно было одинаковое поведение перенаправления во всем приложении. - person ReynierPM; 29.08.2015
comment
Бросить специальное исключение, поймать его в событии kernel.request, перенаправить оттуда. - person user2268997; 30.08.2015
comment
@ user2268997, можете ли вы дать ответ с примером, иллюстрирующим это? - person ReynierPM; 31.08.2015