Я использую следующий код для генерации перенаправления после успешного входа в систему:
$request->request->set('_target_path', $this->router->generate('renew_subscription'));
Выходной URL:
http://mysite.dev/app_dev.php/app_dev.php/renew_subscription
Как я могу убедиться, что app_dev.php не повторяется дважды? Я чувствую, что str_replace не будет достаточно чистым.
РЕДАКТИРОВАТЬ:
Я устанавливаю это в прослушивателе входа. Я понял, что обработчик входа в систему не работает, потому что служба 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 }
Благодаря !
вместо set _target_paath в вашем контроллере или службе вы можете установить его в виде формы:
добавьте это поле в свою форму для входа:
<input type="hidden" name="_target_path" value="YourRouteName" />
"YourRouteName" - это название вашего маршрута
Попробуйте использовать Absolute URL вместо Relative.
$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
Таким образом, есть хороший способ сделать перенаправление, используя обработчик входа. См. Ответ Б. Рад.
Я искал способ сделать это изнутри регистратора входа в систему, потому что когда вы создаете экземпляр обработчика входа, токен еще не заполнен пользователем. Он заполняется только после вызова функции onAuthenticationSuccess
. У меня была зависимость от пользователя, и я сначала загрузил его с помощью конструктора, он не работал. Использование setter и вызов depedency изнутри onAuthenticationSuccess
было решением
В любом случае, мы также можем сделать переадресацию из регистратора входа в систему, используя:
$request = $event->getRequest();
$route = strreplace('app_dev.php', '', $this->router->generate('your_route'))
$request->request->set('_target_path', $route );
Вы должны установить контроллер и использовать 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);
});
}
}
}
}
Подменю Variable - это просто ссылка на имя маршрута, например, место, как показано ниже.
/**
* @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 }
Надеюсь это поможет. Дайте знать, если у вас появятся вопросы.
Если вы пытаетесь запустить перенаправление после входа в систему, вы должны использовать обработчик, как это.
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' }
Я не могу вспомнить, где я выясню, как это сделать, но это было после многих оглядевшихся примеров. У меня также есть обработчик выхода, который я получил с того же места. Я уверен, что если вы ищете имя класса, вы найдете пример где-нибудь.