允许与FOSUserBundle相同的登录只有一个连接(allow only one connect

2019-09-17 06:18发布

我创建一个网站,感谢Symfony2的与FOSUserBundle。

我triyng否认在相同的登录(但是从不同的计算机为例)的多个连接。 我有2个解决方案:

  • 创建于认证的事件听者,但我没能做到这一点。 (甚至与食谱)。
  • 覆盖login_check方法,但如果我做我FOSUserBundle不起作用。

你有什么更好的选择吗? 或者有什么办法呢?

Answer 1:

明白了finaly。 只有一个最后的更新,使解决这一切。 您需要将其他字段添加到用户实体。 的sessionId(字符串)。 然后更新您的LoginListener类这样的:

// YourSite\UserBundle\Listener\YourSiteLoginListener.php

//...
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
    $request = $event->getRequest();
    $session = $request->getSession();
    $user = $event->getAuthenticationToken()->getUser();
    $has_session = is_file ( '/path_to_your_php_session_file/'.'sess_'.$user->getSessionId() );

    if($user->getLogged() && $has_session){
        throw new AuthenticationException('this user is already logged');
    }else{
        $user->setLogged(true);
        $user->setSessionId($session->getId());
        $this->userManager->updateUser($user);
    }   
}


Answer 2:

也许这将帮助人们解决这个问题。

这是一种解决方案,但仍有一个问题:如果用户会话是由PHP打死(后无例如动作太玉米粥时间),你将不得不进入你的数据库,以重置“记录”的值改为0。

所以我的解决办法是:

-add场“记录”(布尔)给你的用户实体。

-in YourSite \ UserBundle \监听器创建一个:YourSiteLoginListener.php使用此代码

namespace YourSite\UserBundle\Listener;

use FOS\UserBundle\Model\UserManagerInterface;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\SecurityContext;


class YourSiteLoginListener
{
private $userManager;

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

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

        if($user->getLogged()){
            throw new AuthenticationException('this user is already logged');
        }else{
            $user->setLogged(true);
            $this->userManager->updateUser($user);
        }   
    }
}

- 然后在同一目录下,创建一个注销处理程序:YourSiteLogoutHandler.php

命名空间YourSite \ UserBundle \监听;

use FOS\UserBundle\Model\UserManagerInterface;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;

class YourSiteLogoutHandler implements LogoutHandlerInterface
{
    private $userManager;

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

    public function logout (Request $request, Response $response, TokenInterface $token){
        $user = $token->getUser();
        if($user->getLogged()){
            $user->setLogged(false);
            $this->userManager->updateUser($user);
        }
    }
}

在您的应用程序/ config.yml例如-finaly声明这些服务:

services:
    yoursite_login_listener:
        class: YourSite\UserBundle\Listener\YourSiteLoginListener
        arguments: [@fos_user.user_manager]
        tags:
            - { name: kernel.event_listener, event: security.interactive_login, method :onSecurityInteractiveLogin }

    yoursite_logout_handler:
        class: YourSite\UserBundle\Listener\YourSiteLogoutHandler
        arguments: [@fos_user.user_manager]


Answer 3:

在Symfony3,注销处理程序不是由上面的代码触发。 我重建代码,以便当用户退出系统更新。

namespace YourSite\UserBundle\Listener;

use FOS\UserBundle\Model\UserManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;

class LogoutSuccessHandler implements LogoutSuccessHandlerInterface
{
    private $userManager;

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


    public function onLogoutSuccess(Request $request){
        global $kernel;
        $user = $kernel->getContainer()->get('security.token_storage')->getToken()->getUser();
        if($user->getLogged()){
            $user->setLogged(false);
            $this->userManager->updateUser($user);
        }
        $referer = $request->headers->get('referer');

        return new RedirectResponse($referer);      
    }
}


文章来源: allow only one connection on the same login with FOSUserBundle