从现有路线重定向到新路线

时间:2015-08-29 16:13:56

标签: php symfony redirect symfony-2.7 symfony-routing

我正在尝试重定向,如果用户未登录(与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(dev)或http://domain.com/app_dev.php/?email=7x-xRFClkjw(prod)之类的链接调用http://domain.com/?email=7x-xRFClkjw路由时,我被重定向到/login。我最好的想法是将我的代码改为:

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

然后redirect using a route到新的/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路线。

3 个答案:

答案 0 :(得分:1)

不确定我是否理解,但您想限制对整个网站的访问?在这种情况下,只需更改您的安全设置,永远不要添加重定向到登录,因为即使登录使用它总是重定向到登录。这是简单的配置示例:

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

access_control:
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/, role: ROLE_USER }

答案 1 :(得分:1)

试试这个:

在yourAction()中的控制器中:

//

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

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

//

答案 2 :(得分:1)

抛出一个特殊的异常,在kernel.request事件中捕获它,从那里重定向。 您必须创建一个自定义例外,您可以将该路线存储在..e.g:

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可以抛出异常或执行重定向到给定路由所需的任何操作。
有关事件监听器的更多信息,请参阅Event Listeners

更新:这正是symfony在您未经过身份验证后将您重定向到login_path的方式,请参阅ExceptionListener