Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 检测Symfony'中的重复登录;福苏斯邦德酒店_Php_Symfony_Fosuserbundle - Fatal编程技术网

Php 检测Symfony'中的重复登录;福苏斯邦德酒店

Php 检测Symfony'中的重复登录;福苏斯邦德酒店,php,symfony,fosuserbundle,Php,Symfony,Fosuserbundle,我在Symfony项目中使用FOSUserBundle,需要删除重复登录。如果用户从其他系统登录,我希望他/她的其他会话断开连接 你能帮我上路吗?嗯,我想这是可能的,但不是现成的,需要一些调整 让我们将问题分解为几个小部分: 会话管理驱动程序 您需要将会话管理驱动程序设置为DB。这可以是任何类型的DBMS(例如,MySQL)。这确保可以查询您的会话 用户名列 默认情况下,会话跟踪数据库表不包括用户名列。您需要更改表,以添加用户名。确保它是NULL-able,否则Symfony将无法写入会话 登录

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


你能帮我上路吗?

嗯,我想这是可能的,但不是现成的,需要一些调整

让我们将问题分解为几个小部分:

  • 会话管理驱动程序

    您需要将会话管理驱动程序设置为DB。这可以是任何类型的DBMS(例如,
    MySQL
    )。这确保可以查询您的会话

  • 用户名列

    默认情况下,会话跟踪数据库表不包括用户名列。您需要
    更改表
    ,以添加
    用户名
    。确保它是
    NULL
    -able,否则
    Symfony
    将无法写入会话

  • 登录成功处理程序

    为防火墙定义登录成功处理程序(在
    security.yml
    中)。该处理程序需要:

    • 提取当前会话id
    • 使用当前登录的用户更新DB表中的记录
    • 执行
      DELETE FROM WHERE username=和session\u id!=
  • 我可能错过了什么,但大致上,就是这个

    希望它能帮助您真正编写自己的解决方案,

    简易方法:

    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;
        }
    }
    
    然后侦听用户每次登录时将触发的事件,并与用户一起保存会话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>
    
    既然您的
    用户
    实体知道哪个会话是最后一个会话,那么您就可以成为
    security.authentication.success
    事件的侦听器,并检查当前会话id是否与最后一个活动会话id匹配。如果没有,那么它就不再是活动会话

    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>
    

    完成-但不应复制/粘贴此内容。尝试理解它的作用,然后编写实现。这应该只是让您了解您可以做什么。可捕获的致命错误:传递给Ipirani\PanelBundle\Security\AuthenticationListener::onAuthenticationSuccess()的参数1必须是Symfony\Component\Security\Http\Event\InteractiveEngineent的实例,Symfony\Component\Security\Core\Event\AuthenticationEvent的实例givencatable致命错误:传递给Ipirani\PanelBundle\Security\AuthenticationListener:的参数1::\uu construct()必须是Symfony\Component\HttpFoundation\RequestStack的实例,FOS\UserBundle\document\UserManager的实例,在第318行的E:\WampDeveloper\webs\ipiraninew.local\webroot\var\cache\prod\appProdDebugProjectContainer.php中调用,definedNow是错误的:当用户未登录时调用字符串上的成员函数GetActiveSessiond(),如何获取sessionid
    $ActiveSessiond=$token->getUser()->GetActiveSessiond()
    
    <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 }