Symfony 4.4.2-带有TokenStorageInterface的EventListener使调试栏显示;加载web调试工具栏时出错。”;
我刚刚将一个应用程序从Symfony 4.3.9升级到4.4.2。之后,调试栏不工作,并显示“加载web调试工具栏时出错” 经过长时间的调查,我发现这是由于security.authentication.failure事件上的EventListener造成的。 注释onAuthenticationFailure方法内容没有任何作用,经过一些调查后,它在从标记和构造函数中删除TokenStorageInterface时起作用。。。但我需要它 有什么想法吗 代码如下: 服务.亚马尔Symfony 4.4.2-带有TokenStorageInterface的EventListener使调试栏显示;加载web调试工具栏时出错。”;,symfony,symfony4,Symfony,Symfony4,我刚刚将一个应用程序从Symfony 4.3.9升级到4.4.2。之后,调试栏不工作,并显示“加载web调试工具栏时出错” 经过长时间的调查,我发现这是由于security.authentication.failure事件上的EventListener造成的。 注释onAuthenticationFailure方法内容没有任何作用,经过一些调查后,它在从标记和构造函数中删除TokenStorageInterface时起作用。。。但我需要它 有什么想法吗 代码如下: 服务.亚马尔 App\
App\EventListener\LoginListener:
arguments: ["@doctrine", "@security.token_storage", "@router", "@event_dispatcher"]
tags:
- { name: kernel.event_listener, event: security.authentication.failure, method: onAuthenticationFailure }
LoginListener.php
<?php
namespace App\EventListener;
use App\Entity\AdminUser;
use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
/**
* Class LoginListener
* Listens to user log in events (failure, interactive log in) to provide additionnal security measures
*
* @package App\EventListener
*/
final class LoginListener
{
protected $doctrine;
protected $request;
protected $tokenStorage;
protected $router;
protected $dispatcher;
/**
* Login constructor.
*
* @param Registry $doctrine
* @param TokenStorageInterface $tokenStorage
* @param RouterInterface $router
* @param EventDispatcherInterface $dispatcher
*/
public function __construct(
Registry $doctrine,
TokenStorageInterface $tokenStorage,
RouterInterface $router,
EventDispatcherInterface $dispatcher
) {
$this->doctrine = $doctrine;
$this->tokenStorage = $tokenStorage;
$this->router = $router;
$this->dispatcher = $dispatcher;
}
/**
* @param AuthenticationFailureEvent $event
* @throws ORMException
* @throws OptimisticLockException
*/
public function onAuthenticationFailure(AuthenticationFailureEvent $event)
{
/** @var EntityManager $em */
$em = $this->doctrine->getManager();
$username = $event->getAuthenticationToken()->getUsername();
/** @var AdminUser $user */
$user = $em->getRepository(AdminUser::class)->findOneBy(['username' => $username]);
if ($user instanceof AdminUser) {
$user->addFailedLogin();
if ($user->getFailedLogin() == 5) {
$user->setLocked(1);
}
$em->persist($user);
$em->flush();
}
}
}
我觉得你做了一个登录验证人所做的工作,但是在错误的地方——当技术上成功登录时,你试图在事后使其失败。在上一个代码块中,您还使用了TokenStorage而不是TokenStorageInterface(这并不是说它有什么区别,这很奇怪)。您的“延迟注销”尝试可能通过自定义用户加载查询得到更好的处理,在这种情况下,您可以执行所有检查,而不返回用户。但是,当用户以非交互方式进行身份验证时,这种方法也会阻止用户。。。
<?php
namespace App\XXXBundle\EventListener;
use App\XXXBundle\Entity\AdminUser;
use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\ORM\EntityManager;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
/**
* Class Login
* Listens to user log in events (failure, interactive log in) to provide additionnal security measures
*
* @package App\XXXBundle\EventListener
*/
class Login
{
protected $doctrine;
protected $request;
protected $tokenStorage;
protected $router;
protected $dispatcher;
/**
* Login constructor.
*
* @param Registry $doctrine
* @param TokenStorage $tokenStorage
* @param RouterInterface $router
* @param EventDispatcherInterface $dispatcher
*/
public function __construct(
Registry $doctrine,
TokenStorage $tokenStorage,
RouterInterface $router,
EventDispatcherInterface $dispatcher
) {
$this->doctrine = $doctrine;
$this->tokenStorage = $tokenStorage;
$this->router = $router;
$this->dispatcher = $dispatcher;
}
/**
* @param AuthenticationFailureEvent $event
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function onAuthenticationFailure(AuthenticationFailureEvent $event)
{
/** @var EntityManager $em */
$em = $this->doctrine->getManager();
$userName = $event->getAuthenticationToken()->getUsername();
/** @var AdminUser $user */
$user = $em->getRepository(AdminUser::class)->findOneByUsername($userName);
if ($user instanceof AdvancedUserInterface) {
$user->addFailedLogin();
if ($user->getFailedLogin() == 5) {
$user->setLocked(1);
}
$em->persist($user);
$em->flush();
}
}
/**
* @param InteractiveLoginEvent $event
* @throws \Exception
*/
public function onInteractiveLogin(InteractiveLoginEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();
if ($user instanceof AdvancedUserInterface) {
$em = $this->doctrine->getManager();
if ($user->getLocked()) {
$this->tokenStorage->setToken(null);
throw new CustomUserMessageAuthenticationException('Compte verrouillé.');
}
if ($user->getExpiresAt() && $user->getExpiresAt() <= new \DateTime()) {
$user->setIsActive(0);
$em->persist($user);
$em->flush();
$this->tokenStorage->setToken(null);
throw new CustomUserMessageAuthenticationException('Compte expiré.');
}
if ($user->getCredentialsExpireAt() && $user->getCredentialsExpireAt() <= new \DateTime()) {
$this->dispatcher->addListener(KernelEvents::RESPONSE, [$this, 'redirectToCredentialsChange']);
}
$user->setLastLogin(new \DateTime());
$user->setFailedLogin(0);
$em->persist($user);
$em->flush();
}
}
public function redirectToCredentialsChange(ResponseEvent $event)
{
$event->getResponse()->headers->set('Location', $this->router->generate('admin_security_changecredentials'));
}
}