28

I need to perform a set of actions after a user successfully logs in. This includes loading data from the database and storing it in the session.

What is the best approach to implementing this?

Carrie Kendall
  • 11,124
  • 5
  • 61
  • 81
jbsound
  • 767
  • 2
  • 9
  • 21
  • 1
    How to do it using a Service: http://stackoverflow.com/questions/8308050/how-to-disable-redirection-after-login-check-in-symfony-2/8312188#8312188 – unairoldan May 06 '13 at 11:40

2 Answers2

54

You can add a listener to the security.interactive_login event.

attach your listener like so. In this example I also pass the security context and session as dependencies.

Note: SecurityContext is deprecated as of Symfony 2.6. Please refer to http://symfony.com/blog/new-in-symfony-2-6-security-component-improvements

parameters:
   # ...

   account.security_listener.class: Company\AccountBundle\Listener\SecurityListener

services:
   # ...

   account.security_listener:
        class: %account.security_listener.class%
        arguments: ['@security.context', '@session']
        tags:
            - { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin }

and in your listener you can store whatever you want on the session. In this case I set the users timezone.

<?php

namespace Company\AccountBundle\Listener;

use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;

class SecurityListener
{

   public function __construct(SecurityContextInterface $security, Session $session)
   {
      $this->security = $security;
      $this->session = $session;
   }

   public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
   {
        $timezone = $this->security->getToken()->getUser()->getTimezone();
        if (empty($timezone)) {
            $timezone = 'UTC';
        }
        $this->session->set('timezone', $timezone);
   }

}
Community
  • 1
  • 1
MDrollette
  • 6,887
  • 1
  • 36
  • 49
  • This looks like it would do the trick. Are there any dependencies I need to declare in the class? – jbsound Jun 24 '12 at 21:25
  • After digging a bit more, seems like there are dependencies that need to be specified. Found this article that shows a more complete code implementation: http://www.metod.si/login-event-listener-in-symfony2/ – jbsound Jun 25 '12 at 02:12
  • There aren't any more dependencies... the only difference with that example is the scope of the listener. – MDrollette Jun 25 '12 at 03:15
  • 25
    You don't need to inject SecurityContext nor Session, you can grab it from InteractiveLoginEvent, using $event->getAuthenticationToken() and $event->getRequest()->getSession(). – Massimiliano Arione Jun 04 '13 at 15:13
  • 3
    Most of the people using YML not XML. And it's a hell of a headache to convert it! – Slavik Meltser Aug 12 '13 at 14:49
  • Plus, you didn't provided namesapces to use. Plus, the scope 'request' will throw an error every time. – Slavik Meltser Aug 12 '13 at 15:01
  • 1
    is it also suitable for the [user impersonalization](http://symfony.com/doc/current/cookbook/security/impersonating_user.html) ? – V-Light Aug 11 '15 at 15:25
  • Does this work even on different session handlers ? What if the project store the sessions in Redis ? – Alucard Nov 06 '15 at 19:26
8

You can even fetch the user instance from the event itself, no need to inject the token storage!

public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
    $event->getAuthenticationToken()->getUser()
}
robinvdvleuten
  • 1,462
  • 1
  • 16
  • 18