0
votes

After a user has logged on, I sign him in automatically.

Automatic login:

// Load $user from database, by activation hash and user id

$user->setLocked('no');
$user->setUnlockedAt(new \DateTime('now'));
$user->setLoginAt(new \DateTime('now'));
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();

$token = new UsernamePasswordToken($user->getUsername(), null, 'main', $user->getRoles()); // "main" = firewall name

$this->get('security.context')->setToken($token); //now the user is logged in

// Now dispatch the login event

$request = $this->get('request');
$event = new InteractiveLoginEvent($request, $token);
$this->get('event_dispatcher')->dispatch('security.interactive_login', $event);

$this->get('session')->set('_security_' . 'main', serialize($token));

Okay, now i added a controller listener. I want it to fire every time a controller is used to update the user's "last activity timestamp" in database. Here is how it looks like right now.

In service.yml i setup the listener event:

services:
  controller_listener:
    class: 'MyComp\MyBundle\Listener\ControllerListener'
    arguments: ['@security.context', '@doctrine']
    tags:
      - { name: 'kernel.event_listener', event: 'kernel.controller', method: 'onKernelController' }

And the listener itself:

<?php

    namespace MyCOmp\MyBundle\Listener;

    use Symfony\Component\Security\Core\SecurityContext;
    use Doctrine\Bundle\DoctrineBundle\Registry;

    class ControllerListener {

        protected $security_context;
        protected $doctrine;

        public function __construct(SecurityContext $securityContext, Registry $doctrine) {
            $this->security_context = $securityContext;
            $this->em = $doctrine->getManager();
        }

        public function onKernelController($event) {

            $controller = $event->getController();

            $token = $this->security_context->getToken();

            if (!is_null($token) && is_object($token->getUser())) {

                $user = $token->getUser();
                $user->setActivityAt(new \DateTime('now'));
                $this->em->persist($user);
                $this->em->flush();

            }

            $event->setController($controller);

        }

    }

As you can see i use $token = $this->security_context->getToken(); $token->getUser() to get the user object to set the "Activity At" value (last activity timestamp).

Now, what happened: After the user gets signed in "automatically", $token->getUser() is not an object. Every time a controller gets used. But after a traditional login via symfony2 forms (login_check and so on), $token->getUser() is a valid user object.

How can it be and what's wrong here?

I think there is a problem with the automatic login, so the sign in process is not complete. Is there any forgotten call?

So i hope you can help me.

Greetings

1

1 Answers

1
votes

Maybe you forget

$token->setUser($user);

before assigning it to security.context?