Symfony2: After Successful Login Event, Perform Set of Actions

Symfony2: After successful login event, perform set of actions

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);
}

}

Symfony 2 after login do some extra job

You can implement a Success Hander.

  1. Write a class that implement the AuthenticationSuccessHandlerInterface:
  2. Define it as a service (you can inject other services like doctrine
    or the security context, in your case the Session)

Add the handler service in the security config like:

firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false

secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: login
check_path: login_check
success_handler: some.service.id
logout:
path: logout
target: /

Check this for a complete example and the reference doc for all the symfony2 security configuration options (you can configure the failure_handler also).

In my working solutions I implements the method onSecurityInteractiveLogin in my listener as:

public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) 
{
$user = $event->getAuthenticationToken()->getUser();

$user->setLastLogin(new \Datetime());
// Entity manager injected by container in the service definition
$this->em->persist($user);
$this->em->flush();

}

Hope this help

Symfony perform action when user login

Method isGranted('IS_AUTHENTICATED_FULLY') is available on Symfony\Component\Security\Core\Authorization\AuthorizationChecker. If you want to check if is user authenticated via token (as in your SecurityListener class), change your onSecurityInteractiveLogin method with this:

public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
if ($event->getAuthenticationToken()->isAuthenticated()) {
$user = $event->getAuthenticationToken()->getUser();
var_dump($user);
}

/**
* Update lastLogin and loginCount for user in database
*/

// $em->

}

Do something just after symfony2 login success and before redirect?

You can specify a login success handler to be executed on successful login.

For example, your security.yml

firewalls:
main:
pattern: ^/
form_login:
success_handler: my.security.login_handler

Now create the class which implements Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface and on successful login, you can do whatever you need and handle the redirect as you see fit.

/**
*
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
// handle it and return a response
}

Then create a service with that name in your services.xml for your bundle, or in your config.yml using the newly created handler.

I originally found out how to do this following this tutorial:

http://www.reecefowell.com/2011/10/26/redirecting-on-loginlogout-in-symfony2-using-loginhandlers/

Symfony 2 - onSecurityAuthenticationSuccess handler gets called on every page load

You have to use the security.interactive_login:


namespace Acme\UserBundle\Listener;

use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Security\Core\SecurityContext;
use Doctrine\Bundle\DoctrineBundle\Registry as Doctrine; // for Symfony 2.1.x
// use Symfony\Bundle\DoctrineBundle\Registry as Doctrine; // for Symfony 2.0.x

/**
* Custom login listener.
*/
class LoginListener
{
/** @var \Symfony\Component\Security\Core\SecurityContext */
private $securityContext;

/** @var \Doctrine\ORM\EntityManager */
private $em;

/**
* Constructor
*
* @param SecurityContext $securityContext
* @param Doctrine $doctrine
*/
public function __construct(SecurityContext $securityContext, Doctrine $doctrine)
{
$this->securityContext = $securityContext;
$this->em = $doctrine->getEntityManager();
}

/**
* Do the magic.
*
* @param Event $event
*/
public function onSecurityInteractiveLogin(Event $event)
{
if ($this->securityContext->isGranted('IS_AUTHENTICATED_FULLY')) {
// user has just logged in
}

if ($this->securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
// user has logged in using remember_me cookie
}

// do some other magic here
$user = $this->securityContext->getToken()->getUser();

// ...
}
}

Symfony 2.5 with FosUserBundle: Add data to the global session after Login

You can add a security interactive login listener, and in that listener you will have access to the login token that is stored in session. This token inherits Symfony\Component\Security\Core\Authentication\Token\AbstractToken so it has the methods "setAttribute($name, $value)" and "setAttributes(array $attributes)". Bassically whatever you set into this property with be stored in session alongside the user and the token.

Just be careful about the fact that this is serialized and make sure if you store objects to implement the serialize/unserialize method if needed in order to not have circular reference problems.

I recommended this approach because it seem to fit your requirements:

  • the token is already stored in session by symfony
  • the token is already accessible in any controller via the service "security.context" found in container,
  • the token is already accessible in twig using the code {{ app.security.getToken() }}

For more information on Authentication Events check the symfony cookbook:
http://symfony.com/doc/current/components/security/authentication.html#authentication-events

Also you can use the following code as a guideline.

In services yml

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

In your 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)
{
$token = $event->getAuthenticationToken();
$token->setAttribute('key','some stuff i want later');
}

}

Hope this helps,

Alexandru Cosoi



Related Topics



Leave a reply



Submit