On peut avoir besoin de connecter un utilisateur via du code, par exemple pour des tests d'url via
steevanb/php-url-test.
La documentation de Symfony est une base pour comprendre le mécanisme, il manque cependant quelques détails.
Vous trouverez ci-dessous un exemple complet, qui créé
LoginListener, pour connecter votre utilisateur avant que le firewall n'essaye de le récupérer.
Notez que pour des raisons de sécurité, je met ce code dans
app/AppTestKernel.php. Ce fichier sera supprimé de l'environnement de prod.
Création du listener dans
AppTestKernel.php :
protected function getContainerBuilder(): ContainerBuilder
{
$container = parent::getContainerBuilder();
$container->setDefinition(
'foo.login_event_listener',
new Definition(
LoginEventListener::class,
[
new Reference('security.token_storage'),
new Reference('foo.user_provider'),
new Reference('event_dispatcher'),
new Reference('session'),
new Reference('request_stack')
]
)
);
return $container;
}
Ajout du listener sur
kernel.request, dans
AppTestKernel.php :
public function boot(): void
{
parent::boot();
$this
->getContainer()
->get('event_dispatcher')
// priorité 9 parceque le firewall qui redirige sur la page de login a une priorité de 8
->addListenerService('kernel.request', ['foo.login_event_listener', 'login'], 9);
}
Listener qui log le user
admin :
<?php
declare(strict_types=1);
namespace Foo;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\{
RequestStack,
Session\SessionInterface
};
use Symfony\Component\Security\{
Core\Authentication\Token\Storage\TokenStorageInterface,
Core\Authentication\Token\UsernamePasswordToken,
Core\User\UserProviderInterface,
Http\Event\InteractiveLoginEvent
};
class LoginEventListener
{
/** @var TokenStorageInterface */
protected $tokenStorage;
/** @var UserProviderInterface */
protected $userProvider;
/** @var EventDispatcherInterface */
protected $eventDispatcher;
/** @var SessionInterface */
protected $session;
/** @var RequestStack */
protected $requestStack;
public function __construct(
TokenStorageInterface $tokenStorage,
UserProviderInterface $userProvider,
EventDispatcherInterface $eventDispatcher,
SessionInterface $session,
RequestStack $requestStack
) {
$this->tokenStorage = $tokenStorage;
$this->userProvider = $userProvider;
$this->eventDispatcher = $eventDispatcher;
$this->session = $session;
$this->requestStack = $requestStack;
}
public function login(GetResponseEvent $event): void
{
// récupération de l'utilisateur et connexion
$user = $this->userProvider->loadUserByUsername('admin');
$token = new UsernamePasswordToken(
$user,
$user->getPassword(),
'main',
$user->getRoles()
);
$this->tokenStorage->setToken($token);
// l'événement security.interactive_login n'est pas lancé automatiquement
$event = new InteractiveLoginEvent($event->getRequest(), $token);
$this->eventDispatcher->dispatch('security.interactive_login', $event);
// http://symfony.com/doc/current/testing/http_authentication.html
// sauvegarde du token dans la session, pour que le firewall le retrouve
$this->session->set('_security_main', serialize($token));
$this->session->save();
// création du cookie
// si on ne le fait pas, le firewall redirige sur la page de connexion
$this->requestStack->getCurrentRequest()->cookies->set(
$this->session->getName(),
$this->session->getId()
);
}
}
Documentation Symfony