2012-05-16 18 views
0

我正在创建一个网站,感谢Symfony2与FOSUserBundle。只允许一个连接与FOSUserBundle登录相同

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

  • 创建事件列表验证,但我没有设法做到这一点。 (即使有食谱)。
  • 重写login_check方法,但我的FOSUserBundle不起作用,如果我这样做。

您有更好的选择吗? 或者任何解决方案?

+0

FYI这里是SO另一种解决方案:http://stackoverflow.com/questions/13514513/prevent-duplicate-login-with-fosuserbundle –

回答

0

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

这是一种解决方案,但仍然存在一个问题: 如果用户会话被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] 
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); 
    } 
} 
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);  
    } 
}