如何强制注销Symfony中的用户?

tft*_*ftd 3 php authentication symfony

我有一个User实体,它有一个布尔列isActivated.根据每个用户的列值,他可能会或可能无法登录(即他没有激活他的帐户,因此无法登录).我通过simple_form.authenticator在防火墙中分配一个检查每次登录来实现这一点.

我正在试图找出当用户仍在进入时如何强制注销用户.
请考虑以下情形:

  1. 用户在其帐户仍处于活动状态时登录.
  2. 管理员停用该用户的帐户.
  3. 用户因其不再处于活动状态而被注销.

不幸的是,第3步没有发生.原因可能在于用户已经收到令牌并且被Symfony 2.5防火墙视为"被"攻击(可能是令牌被缓存在安全上下文中?).

我想知道克服这个问题的最佳方法是什么?我应该编写内核事件监听器还是自定义用户提供程序?

lxg*_*lxg 6

您可以使用以下两行终止用户的会话(如果您有权访问容器,否则必须注入security.context和session):

$container->get('security.context')->setToken(null);
$container->get('session')->invalidate();
Run Code Online (Sandbox Code Playgroud)

之后,用户应该注销.

如果您之前加载了用户实体,您也可能想要取消设置.


tft*_*ftd 5

虽然@lxg回答了我的问题,但我决定扩展他的答案,以便其他有同样问题的人更好地了解如何解决这个问题.

创建事件侦听器

namespace Acme\MyBundle\Events;

use Acme\MyBundle\Entity\User;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\SecurityContext;

class RequestEvent {

    /**
     * @var \Symfony\Component\Security\Core\SecurityContext
     */
    private $securityContext;

    public function __construct(SecurityContext $context){
        $this->securityContext = $context;
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        // not sure if this is actually needed?
        if (!$event->isMasterRequest()) {
            // don't do anything if it's not the master request
            return;
        }

        // try to get security context and catch the exception in case no firewall was configured (i.e. for the dev tool bar)
        try{
            // trigger only for logged in users
            if($this->securityContext->isGranted('IS_AUTHENTICATED_FULLY')){
                $token = $this->securityContext->getToken();
                /**
                 * @var User $user
                 */
                $user = $token->getUser();
                if($user != null && !$user->isActive()){
                    $this->securityContext->setToken(null);
                }
            }
        } catch(AuthenticationCredentialsNotFoundException $e){
            // don't do anything here... or do whatever you want.
        }
    }
}

?>
Run Code Online (Sandbox Code Playgroud)

现在在你的service.yml添加中:

services:
    kernel.listener.request_listener:
        class: Acme\MyBundle\Events\RequestEvent
        arguments: [ @security.context ]
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
Run Code Online (Sandbox Code Playgroud)

一旦用户被停用,他就会被强制重定向到防火墙的登录页面.希望这有助于某人.