0

感谢 Symfony2 和 FOSUserBundle,我正在创建一个网站。

我试图在同一登录名上拒绝多个连接(例如来自不同的计算机)。我有 2 个解决方案:

  • 创建一个关于身份验证的事件监听器,但我没能成功。(即使有食谱)。
  • 覆盖 login_check 方法,但如果我这样做,我的 FOSUserBundle 将不起作用。

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

4

3 回答 3

1

终于明白了 只需进行最后一次更新即可解决所有问题。您需要向 User 实体添加其他字段。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);
    }   
}
于 2012-05-25T07:33:10.827 回答
0

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

这是一种解决方案,但仍然存在问题:如果用户会话被 php 杀死(例如,在没有采取行动的时间太长之后),您将不得不进入数据库将“记录”值重置为 0。

所以我的解决方案是:

- 将字段“记录”(布尔)添加到您的用户实体。

-in YourSite\UserBundle\Listener 创建一个: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\Listener;

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);
        }
    }
}

-finaly 在您的 app/config.yml 中声明这些服务,例如:

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]
于 2012-05-23T13:12:20.047 回答
0

在 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);      
    }
}
于 2016-12-30T11:37:13.370 回答