mardi 23 mai 2017

Connexion d'un User dans Symfony via un Listener

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

Aucun commentaire:

Publier un commentaire