symfony2在请求头中设置_target_path会重复app_dev.php

symfony2在请求头中设置_target_path会重复app_dev.php,php,symfony,login,Php,Symfony,Login,我正在使用以下代码在成功登录后生成重定向: $request->request->set('_target_path', $this->router->generate('renew_subscription')); 输出url为: 如何确保app_dev.php不会重复两次?我觉得Stru_不够干净 编辑: 我正在登录侦听器中设置此选项。我发现登录处理程序无法工作,因为securitymanager服务尚未正确启动: portfolio_change_and_log

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

$request->request->set('_target_path', $this->router->generate('renew_subscription'));
输出url为:

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

编辑:


我正在登录侦听器中设置此选项。我发现登录处理程序无法工作,因为securitymanager服务尚未正确启动:

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 }

谢谢

您可以在窗体视图中设置它,而不是在控制器或服务中设置\u target\u paath:

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

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


“YourRouteName”是路线的名称

您应该设置控制器并使用重定向响应

这是一个监听器,我用它来确保下一条路线是表单中计划好的下一步,这样用户就不会到处乱跳。我查查看是否

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' } 

我不记得我在哪里找到了如何做到这一点,但这是在到处寻找例子之后。我也有一个注销处理程序,我从同一个地方得到。我相信如果你搜索类名,你会在某处找到这个例子

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

我一直在寻找一种在登录侦听器中实现它的方法,因为当您实例化登录处理程序时,令牌还没有被用户填充。只有在您调用AuthenticationSuccess后,才会填充它。 我对用户有依赖性,我首先用构造函数加载它,但它不起作用。使用setter并从
内部调用对AuthenticationSuccess
的依赖性是解决方案

无论如何,我们也可以从登录侦听器执行重定向,使用:

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

尝试使用绝对URL而不是相对URL

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

文档

您在哪里设置此设置?我在登录侦听器中设置此设置。不适用于我的情况,我在登录侦听器中设置此设置。好的,我希望在登录检查和成功身份验证后重定向此设置。如果symfony正在处理检查部分,我如何使用控制器?您是使用fos用户包还是仅使用symfony?我使用fosub,yes@S我在下半场更新了我的答案。我想这应该可以解决你的问题。嗯,不幸的是,在我的情况下,我需要一个登录列表。我已经尝试过登录处理程序,除了我依赖于某个没有及时更新的东西(我有另一个服务将tokenstorage作为参数,并且这个token还没有填充用户信息)之外,其他都可以正常工作