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.
- Write a class that implement the
AuthenticationSuccessHandlerInterface
: - 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
PHP Printed Boolean Value Is Empty, Why
How to Create a Subquery Using Laravel Eloquent
PHP Date() in Foreign Languages - E.G. Mar 25 Aoû 09
Difference Between PHP Echo and Return in Terms of a Jquery Ajax Call
Generate Cryptographically Secure Random Numbers in PHP
How to Handle Multiple File Upload Using PHP
Another Twitter Oauth Curl Access Token Request That Fails
How to Solve a Timeout Error in Laravel 5
Undefined Class Constant 'Mysql_Attr_Init_Command' with Pdo
Pdo Drivers No Value in Windows
Constant Expression Contains Invalid Operations
Is MySQL_Real_Escape_String() Necessary When Using Prepared Statements
PHP & Sessions: How to Disable PHP Session Locking
Changing the Root Folder via .Htaccess