如何在Symfony 2.7中关闭用户的所有会话?

时间:2016-04-23 18:16:55

标签: php symfony symfony-2.7

用户更改密码后(在恢复密码操作中),我需要使连接到该用户的所有会话无效(他可能登录多个浏览器/设备)。因此,在我使用新密码在数据库中保存用户之后,我需要关闭在该用户的不同浏览器/设备中可能处于活动状态的所有会话。我试过这个:

$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get('security.token_storage')->setToken($token);

也尝试过:

$this->get('security.token_storage')->getToken()->setAuthenticated(false);

这也是:

$this->get('security.token_storage')->setToken(null);

提前致谢!

我已将此添加到我的用户类:

class User implements UserInterface, EquatableInterface, \Serializable{
  // properties and other methods

  public function isEqualTo(UserInterface $user){
    if ($user->getPassword() !== $this->getPassword()){
        return false;
    }
    if ($user->getEmail() !== $this->getEmail()){
        return false;
    }
    if ($user->getRoles() !== $this->getRoles()){
        return false;
    }
    return true;
  }


  /** @see \Serializable::serialize() */
  public function serialize()
  {
    return serialize(array(
        $this->id,
        $this->email,
        $this->password,
        // see section on salt below
        // $this->salt,
    ));
  }

  /** @see \Serializable::unserialize() */
  public function unserialize($serialized)
  {
    list (
        $this->id,
        $this->email,
        $this->password,
        // see section on salt below
        // $this->salt
    ) = unserialize($serialized);
  }
}

4 个答案:

答案 0 :(得分:6)

您需要跟踪该用户打开的每个会话。由于他可能登录多个浏览器/设备,因此他可能会使用不同的会话。

一种简单的方法是将会话ID的引用与用户ID一起保存,以便您可以获得用户的所有信息。

namespace AppBundle\Security;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;

class LoginListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            SecurityEvents::INTERACTIVE_LOGIN => 'onSecurityInteractiveLogin',
        );
    }

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

        /*
         * Save $user->getId() and $session->getId() somewhere
         * or update it if already exists.
         */
    }
}

然后注册一个security.interactive_login事件,每次用户登录时都会触发该事件。然后您可以使用

注册该监听器
<service id="app_bundle.security.login_listener" class="AppBundle\Security\LoginListener.php">
    <tag name="kernel.event_subscriber" />
</service> 

之后,当您想要撤消用户的所有会话时,您需要做的就是检索该用户的所有会话ID,使用

循环并销毁它们
$session = new Session();
$session->setId($sessid);
$session->start();
$session->invalidate();

答案 1 :(得分:2)

Sebcar,

这是Symfony Security本身的一个错误: Bug explanation to be review First Bug

所以你必须覆盖抽象令牌

答案 2 :(得分:1)

根据默认设置中的documentation,您应该已经发生了。

  

例如,如果2个User对象上的用户名由于某种原因不匹配,则出于安全原因,用户将被注销。 (......)   Symfony还使用用户名,salt和密码来验证用户在请求之间没有更改

我不知道您的用户是如何配置的,但您可能需要实施EquatableInterface

答案 3 :(得分:0)

尝试$session->clear();

检查SimpleDateFormat

相关问题