Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Symfony 3.4:如何强制取消身份验证_Symfony_Security - Fatal编程技术网

Symfony 3.4:如何强制取消身份验证

Symfony 3.4:如何强制取消身份验证,symfony,security,Symfony,Security,我的安全用户通过从某个系统获得的某些角色进行了完全身份验证。我想检查其中一个角色是否存在,如果不存在,我想强制用户取消身份验证 在登录时的事件侦听器中,我执行以下操作: use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Co

我的安全用户通过从某个系统获得的某些角色进行了完全身份验证。我想检查其中一个角色是否存在,如果不存在,我想强制用户取消身份验证

在登录时的事件侦听器中,我执行以下操作:

use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

class SecurityEventSubscriber implements EventSubscriberInterface {
  private $token;
  private $checker;
  private $container;
  private $session;

  public function __construct(TokenStorageInterface $token, AuthorizationCheckerInterface $checker, ContainerInterface $container, SessionInterface $session) {
    $this->token = $token;
    $this->checker = $checker;
    $this->container = $container;
    $this->session = $session;
  }


  public function login() {  
    if(!$this->checker->isGranted('IS_AUTHENTICATED_FULLY')) {
        $this->session->invalidate();
        $this->token->setToken(null);
        throw new AccessDeniedException();
    } else {
        $user = $this->token->getToken()->getUser();
        $roles = $user->getRoles();
        $found = false;

        foreach ($roles as $role) {
            if($role->getRole() === $this->container->getParameter('role_expected')) {
                $found = true;
                break;
            }
        }

        if(!$found) {
            $this->session->invalidate();
            $this->token->setToken(null);
            throw new AccessDeniedException();
        } else {
            $user->removeAllRoles();
        }
    }
  }
}
正如您所看到的,我试图使用setToken将其设置为null,但它不起作用(异常)


HGow我应该要求取消对用户的身份验证吗?

最简单的方法是将用户重定向到注销路径

遗憾的是,似乎没有一个专门的方法可以简单地为您处理整个注销过程。 除非您设法调用了
Symfony\Component\Security\Http\Firewall\LogoutListener
的有效实例

Symfony注销的工作原理如下:

  • 它由这个侦听器处理
  • 每个请求都会调用侦听器
  • 侦听器检查请求的路由是否===注销路由
  • 如果请求的路由===注销路由,侦听器将注销用户

您可以创建一个自定义用户检查器,根据您的自定义逻辑拒绝身份验证,而不是检查控制器中的用户权限

示例用户检查程序

namespace AppBundle\Security;
use AppBundle\Security\User as AppUser;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class UserChecker implements UserCheckerInterface
{
    public function checkPreAuth(UserInterface $user)
    {
        if (!$user instanceof AppUser) {
            return;
        }

        if (!in_array('SOME_ROLE', $user->getRoles())) {
            // throw an AccountStatusException exception here
        }
    }
}
如果您还希望在用户登录后对用户角色进行检查(如果他的角色在会话期间可能发生更改),则可以使用
checkPostAuth()
方法


您还必须提到在
app/config/security.yml
文件中使用自定义用户检查器

security:
    firewalls:
        main:
            pattern: ^/
            user_checker: AppBundle\Security\UserChecker

更多信息

当侦听器自身被实例化时,会话可能尚未创建。您可以尝试注入RequestStack,然后在登录方法中从主请求获取会话。不确定它是否真的有用。虽然不相关,但您也应该仅使用role_预期参数替换容器。您似乎需要检查正在验证的用户的角色。如果用户角色不包含您想要拒绝他的身份验证的角色,对吗?似乎使用注销路由只是从会话中删除用户,但是如果我查看开发工具栏,用户仍然是经过身份验证的。我想做的不是在工具栏中看到经过身份验证的,只是为了确定。用户仍然经过身份验证:有可能,用户是匿名身份验证的吗?