我遇到的问题是我试图将用户自动登录到我网站的个人资料部分,但由于受到symfony防火墙的保护,用户会在自动登录系统启动之前被重定向到登录页面。
所以我想知道当用户试图访问我可以收听的防火墙下的页面时,是否会触发一个事件,或者最终我可以使用其他机制解决这个问题。
目前我修复的目的是创建一个自定义重定向控制器,我将用户发送给autologin hash和一个包含最终位置的路径参数以便发送给用户,因此在对其进行身份验证后,我将其重定向到最终目的地。
我想要实现的目标是能够将用户直接自动登录到防火墙后面的那些页面,而无需使用自定义控制器对用户进行自动登录,然后将其重定向到所需的页面。
谢谢。
d
答案 0 :(得分:0)
基本上,您有三种选择:
如果您想真正收听防火墙,则需要创建自定义身份验证提供程序,这是一项具有挑战性的任务。
您可以在文档中遵循本指南:http://symfony.com/doc/current/security/custom_authentication_provider.html 或http://sirprize.me/scribble/under-the-hood-of-symfony-security/
这里的要点是创建自己的防火墙侦听器,它决定是否对用户进行身份验证。防火墙可以有多个侦听器。
或者,您可以收听kernel.request
事件,可能会手动检查您是否在安全路径上,如果是,则通过帮助方法手动验证用户。例如:
namespace AppBundle\Subscriber;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
class RequestSubscriber implements EventSubscriberInterface
{
private $tokenStorage;
private $eventDispatcher;
public function __construct(TokenStorageInterface $tokenStorage, EventDispatcherInterface $eventDispatcher)
{
$this->tokenStorage = $tokenStorage;
$this->eventDispatcher = $eventDispatcher;
}
public static function getSubscribedEvents()
{
return [ KernelEvents::REQUEST => 'onRequest' ];
}
public function onRequest(GetResponseEvent $event)
{
// only master requests and not authenticated users
if (!$event->isMasterRequest() || $this->isUserLoggedIn()) {
return;
}
// add your own logic for creating or loading a User object
// and filtering secured routes
/* ... */
// wohoo, user is going to be logged in manually!
$this->authenticate($user, $event->getRequest(), 'secured_area');
}
protected function authenticate(UserInterface $user, Request $request, String $provider) : Bool
{
// password doesn't matter in this case
$token = new UsernamePasswordToken($user, null, $provider, $user->getRoles());
// actual authenticating
$this->tokenStorage->setToken($token);
// dispatch the authentication event, so event listeners can do stuff
$loggedUser = $token->getUser();
if ($loggedUser instanceof UserInterface && $loggedUser->isAccountNonLocked() &&
$loggedUser->isEnabled()) {
$this->eventDispatcher
->dispatch(
SecurityEvents::INTERACTIVE_LOGIN,
new InteractiveLoginEvent($request, $token)
);
return true;
}
return false;
}
protected function isUserLoggedIn()
{
$token = $this->tokenStorage->getToken();
if (!$token) {
return false;
}
return ($token->getUser() instanceof UserInterface);
}
}
并且不要忘记将其添加到 app / config / services.yml :
app.request_subscriber:
class: AppBundle\Subscriber\RequestSubscriber
tags:
- { name: kernel.event_subscriber }
arguments: ['@security.token_storage', '@event_dispatcher']
(可能不适合您,因为您要进行身份验证,而不是授权用户,但我仍然会为其他人提及。)
在 app / config / security.yml 中,更改访问控制设置,以便每个人都可以访问安全区域:
# ...
access_control:
- { path: ^/secured-area$, role: IS_AUTHENTICATED_ANONYMOUSLY }