我创建一个网站,感谢Symfony2的与FOSUserBundle。
我triyng否认在相同的登录(但是从不同的计算机为例)的多个连接。 我有2个解决方案:
- 创建于认证的事件听者,但我没能做到这一点。 (甚至与食谱)。
- 覆盖login_check方法,但如果我做我FOSUserBundle不起作用。
你有什么更好的选择吗? 或者有什么办法呢?
我创建一个网站,感谢Symfony2的与FOSUserBundle。
我triyng否认在相同的登录(但是从不同的计算机为例)的多个连接。 我有2个解决方案:
你有什么更好的选择吗? 或者有什么办法呢?
明白了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);
}
}
也许这将帮助人们解决这个问题。
这是一种解决方案,但仍有一个问题:如果用户会话是由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]
在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);
}
}