gpt4 book ai didi

php - 在 Symfony 的 FOSUserBundle 中检测重复登录

转载 作者:搜寻专家 更新时间:2023-10-31 21:24:01 25 4
gpt4 key购买 nike

我在我的 Symfony 项目中使用 FOSUserBundle,我需要删除重复的登录。如果用户从不同的系统登录,我希望他/她的其他 session 断开连接。

你能帮我一下吗?

最佳答案

简单的方法:

activeSessionId 字段映射到您的 User 类:

/**
* @ORM\Entity
* @ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;

/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
protected $activeSessionId;

public function loginWithSessId($sessionId)
{
$this->activeSessionId = $sessionId;
}

public function logout()
{
$this->activeSessionId = null;
}

public function getActiveSessId()
{
return $this->activeSessionId;
}
}

然后听security.interactive_login每次用户登录时都会触发的事件,并与用户一起保存 session ID 的引用:

namespace AppBundle\Security;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use FOS\UserBundle\Model\UserManagerInterface;

class LoginListener implements EventSubscriberInterface
{
private $userManager;

public function __construct(UserManagerInterface $userManager)
{
$this->userManager = $userManager;
}

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

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

$user->loginWithSessId($session->getId());
$this->userManager->updateUser($user);
}
}

然后您可以通过以下方式注册监听器:

<service id="app_bundle.security.login_listener" class="AppBundle\Security\LoginListener">
<argument type="service" id="fos_user.user_manager"/>
<tag name="kernel.event_subscriber" />
</service>

# app/config/services.yml
services:
app_bundle.security.login_listener:
class: AppBundle\Security\LoginListener
arguments: ['@fos_user.user_manager']
tags:
- { name: kernel.event_subscriber }

现在您的 User 实体知道哪个 session 是最后一个,您可以创建一个 security.authentication.success 事件的监听器,并检查当前 session 是否id 与最后一个事件的匹配。如果不是,则它不再是事件 session 。

namespace AppBundle\Security;

use Symfony\Component\Security\Core\AuthenticationEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\HttpFoundation\RequestStack;
use FOS\UserBundle\Model\UserManagerInterface;

class AuthenticationListener implements EventSubscriberInterface
{
private $requestStack;
private $userManager;

public function __construct(RequestStack $requestStack, UserManagerInterface $userManager)
{
$this->requestStack = $requestStack;
$this->userManager = $userManager;
}

public static function getSubscribedEvents()
{
return array(
AuthenticationEvents::AUTHENTICATION_SUCCESS => 'onAuthenticationSuccess',
);
}

public function onAuthenticationSuccess(AuthenticationEvent $event)
{
$token = $event->getAuthenticationToken();
$sessionId = $this->requestStack->getMasterRequest()->getSession()->getId();
$activeSessId = $token->getUser()->getActiveSessId();

if ($activeSessId && $sessionId !== $activeSessId) {
$token->setAuthenticated(false); // Sets the authenticated flag.
}
}
}

最后:

<service id="app_bundle.security.auth_listener" class="AppBundle\Security\AuthenticationListener">
<argument type="service" id="request_stack"/>
<argument type="service" id="fos_user.user_manager"/>
<tag name="kernel.event_subscriber" />
</service>

# app/config/services.yml
services:
app_bundle.security.auth_listener:
class: AppBundle\Security\AuthenticationListener
arguments: ['@request_stack', '@fos_user.user_manager']
tags:
- { name: kernel.event_subscriber }

关于php - 在 Symfony 的 FOSUserBundle 中检测重复登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40356211/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com