请求标头中的symfony2设置_target_path重复app_dev.php

时间:2015-03-28 00:34:46

标签: php symfony login

我使用以下代码在成功登录后生成重定向:

$request->request->set('_target_path', $this->router->generate('renew_subscription'));

输出网址为:

  

http://mysite.dev/app_dev.php/app_dev.php/renew_subscription

如何确保app_dev.php不会重复两次?我觉得str_replace不够干净。

编辑:

我在登录监听器中设置它。我发现登录处理程序无法正常工作,因为安全管理器服务尚未正确启动:

portfolio_change_and_login_listener:
    class: %portfolio_change_and_login_listener.class%
    arguments: [@security.authorization_checker, @doctrine.orm.entity_manager, @session, @security_manager, @router]
    tags:
        - { name: kernel.event_listener, event: portfolio_change, method: onPortfolioUserChange }
        - { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin, priority: 255 }

谢谢!

4 个答案:

答案 0 :(得分:2)

而不是在控制器或服务中设置_target_paath,您可以在表单视图中设置它:

将此字段添加到您的登录表单中:

<input type="hidden" name="_target_path" value="YourRouteName" />

&#34; YourRouteName&#34;是您的路线名称

答案 1 :(得分:0)

您应该设置控制器并使用RedirectResponse

这是一个监听器,我用它来确保下一个路由是表单中计划的下一步,这样用户就无法跳转。我查看是否

use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class SampleListener
{
    protected $em;
    protected $token_storage;
    private $router;

    function __construct(TokenStorageInterface $token_storage, EntityManager $em, $router)
    {
        $this->token_storage = $token_storage;
        $this->em = $em;
        $this->router = $router;
    }

    public function onKernelController(FilterControllerEvent $event)
    {

        //some other checks go here

        $route = $event->getRequest()->attributes->get("_route");
        $appStep = $app->getAppStep();


        if ($route != $appStep) {
            //Check to see if the route is going to the planned next stp
            $stepsVisited = explode(",", $app->getVisited());
            if (in_array($route, $stepsVisited)) {
                //if its not going to the next planned step then make sure its a path we visited before.
                return;

            } else {

                $url = $this->router->generate($appStep, array("appId" => $appId));
                $event->setController(function () use ($url) {
                    return new RedirectResponse($url);
                });
            }
        }
    }
}

变量appstep只是对路径名称的引用,如下所示。

/**
 * @Route("/place/{appId}", name="Place")
 */

这就是我的服务。这是在yml

中完成的
sample.action_listener:
        class: Bundle\Name\EventListener\AppSecurityListener
        arguments:
            - @security.token_storage
            - @doctrine.orm.entity_manager
            - @router
        tags:
            - { name: kernel.event_listener, event: kernel.controller, method: onKernelController }

希望这会有所帮助。如果您有任何疑问,请告诉我。


编辑1

如果您尝试在登录后运行重定向,那么您应该使用这样的处理程序。

use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Router;

class LoginSuccessHandler implements AuthenticationSuccessHandlerInterface
{

    protected $router;
    protected $security;

    public function __construct(Router $router, SecurityContext $security)
    {
        $this->router = $router;
        $this->security = $security;
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {

        if ($this->security->isGranted('ROLE_ADMIN')) {
            $response = new RedirectResponse($this->router->generate('AnnotationName 4'));
        } elseif ($this->security->isGranted('ROLE_B')) {
            $response = new RedirectResponse($this->router->generate('AnnotationName1'));
        }
//        elseif ($this->security->isGranted('ROLE_ADMIN'))
//        {
//            // redirect the user to where they were before the login process begun.
//            $referer_url = $request->headers->get('referer');
//
//            $response = new RedirectResponse($referer_url);
//        }
        else {
            $response = new RedirectResponse($this->router->generate('Home'));
        }

        return $response;
    }
}

然后,您需要在服务文件中设置参数和服务

parameters:
    bundle_name.service.login_success_handler.class: Bundle\Name\Service\LoginSuccessHandler
services:
    bundle_name.service.login_success_handler:
        class:  %bundle_name.service.login_success_handler.class%
        arguments:  [@router, @security.context]
        tags:
            - { name: 'monolog.logger', channel: 'security' } 

我无法记住我在哪里弄清楚如何做到这一点,但经过大量的环顾四周寻找例子。我也有一个登出处理程序,我从同一个地方。我相信如果你搜索类名,你会在某个地方找到这个例子。

答案 2 :(得分:0)

因此,有一种使用登录处理程序进行重定向的好方法。 见B. Rad答案。

我一直在寻找一种从登录侦听器中创建它的方法,因为当您实例化登录处理程序时,该令牌尚未填充该用户。仅在您致电onAuthenticationSuccess后填充。 我有一个依赖用户,我首先用构造函数加载它,它不起作用。使用setter并从onAuthenticationSuccess内调用依赖是解决方案

无论如何,我们也可以使用以下命令从登录监听器进行重定向:

$request = $event->getRequest();
$route = strreplace('app_dev.php', '', $this->router->generate('your_route'))
$request->request->set('_target_path', $route );

答案 3 :(得分:0)

尝试使用绝对URL代替相对URL。

$request = $event->getRequest();
$route = $this->router->generate('your_url', [], UrlGeneratorInterface::ABSOLUTE_URL)
$request->request->set('_target_path', $route);

文档https://symfony.com/doc/current/routing.html#generating-absolute-urls