所以我有这个基本的网络应用程序,只有一个用户(我)可以访问受保护的后台区域。我希望能够在其他设备(另一台计算机,我的手机等)上远程注销我的会话。
通过这种方式,我实现了session
表:
CREATE TABLE IF NOT EXISTS `session` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`session_token` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`login_date` datetime NOT NULL,
`user_agent` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`ip` varchar(15) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_D044D5D4844A19ED` (`session_token`),
KEY `IDX_D044D5D4A76ED395` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=15 ;
以及适当的处理程序:
<?php
namespace AppBundle\Event\Listener;
// use ...
class LoginListener implements EventSubscriberInterface
{
protected $em;
function __construct(EntityManager $em)
{
$this->em = $em;
}
public static function getSubscribedEvents()
{
return array(
SecurityEvents::INTERACTIVE_LOGIN => 'onSecurityInteractiveLogin',
);
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();
$currentSession = $event->getRequest()->getSession();
$session = (new \AppBundle\Entity\Admin\Session)
->setUser($user)
->setSessionToken($currentSession->getId())
;
$this->em->persist($session);
$this->em->flush();
}
}
<?php
namespace AppBundle\Event\Listener;
// use ...
class LogoutListener implements LogoutSuccessHandlerInterface {
private $tokenStorage;
private $router;
private $em;
public function __construct(TokenStorage $tokenStorage, Router $router, EntityManager $em)
{
$this->tokenStorage = $tokenStorage;
$this->router = $router;
$this->em = $em;
}
public function onLogoutSuccess(Request $request)
{
$session = $this
->em
->getRepository('AppBundle:Admin\Session')
->findOneBySessionToken($request->getSession()->getId());
$this->em->remove($session);
$this->em->flush();
$response = new RedirectResponse($this->router->generate('blog_home'));
$response->headers->clearCookie('remember_me');
$response->headers->clearCookie('session');
$response->send();
$request->getSession()->invalidate();
return $response;
}
}
这在处理登录和注销时很有效。记录在登录时正确插入,在注销时删除。现在,我可以执行以下操作来远程使会话无效:
public function clearSessionsAction(Request $request)
{
$session = new Session();
session_id('<whatever remote session id found in session table>');
$session->invalidate();
return $this->redirect($this->generateUrl('blog_home'));
}
但是,如果我在登录时选中“记住我”进行远程会话,这将无效。
因此,我的问题是:是否可以为当前的其他用户清除“remember_me”cookie?
当然,我尝试$response->headers->clearCookie('remember_me');
,但这结束了当前会话。
答案 0 :(得分:1)
您无法清除另一个会话的Cookie,因为该会话的浏览器必须先发送请求,然后才能告诉它删除Cookie。这是一种不安全的方式来记录人们,因为任何有权访问cookie的人都可以手动重新添加它并重用会话。
实现此目的的正确方法是使用PdoSessionHandler
将会话实际存储在SQL数据库中,然后如果要远程登录用户,则只需删除数据库中的会话即可。