用户更改密码后(在恢复密码操作中),我需要使连接到该用户的所有会话无效(他可能登录了多个浏览器/设备)。因此,在数据库中保存具有新密码的用户后,我需要关闭该用户在不同浏览器/设备中可能处于活动状态的所有会话。我试过这个:
$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);
}
}
您需要跟踪该用户打开的每个会话。由于他可能登录多个浏览器/设备,因此他可能会使用不同的会话。
一个简单的方法是将会话 id 的引用与用户 ID 一起保存,以便您可以获取用户的所有 sessid。
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();
Sebcar,
这是Symfony Security本身的一个错误:待审查的错误解释第一个错误
所以你将不得不覆盖抽象令牌
根据默认设置中的文档,您应该已经发生了。
例如,如果 2 User 对象上的用户名由于某种原因不匹配,则出于安全原因,用户将被注销。(...) Symfony还使用用户名,salt和密码来验证用户在请求之间没有更改
我不知道您的用户是如何配置的,但您可能需要实现 EquatableInterface
尝试$session->clear();
查看文档