如何在Symfony 4中记录登录失败?

3

我的问题

我需要返回什么样的响应才不会改变默认响应? 或者有更好的方法来追踪登录失败/坏凭据异常?

详情

我在这个帖子中找到了答案(链接),它说明您可以(在Symfony 2.4中)像这样自定义身份验证失败或成功:

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class CustomTimeAuthenticator extends TimeAuthenticator implements AuthenticationFailureHandlerInterface, AuthenticationSuccessHandlerInterface
{
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        error_log('You are out!');
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {
        error_log(sprintf('Yep, you are in "%s"!', $token->getUsername()));
    }
}

它还指出,您可以通过返回一个 Response 实例来完全绕过默认行为:
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
    if ($exception->getCode()) {
        return new Response('Not the right time to log in, come back later.');
    }
}

很不幸,似乎在Symfony 4中必须返回一个响应(与上述2.4代码不同),因此我的代码如下:

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Psr\Log\LoggerInterface;

class LoginFailureLogger implements AuthenticationFailureHandlerInterface
{
    private $logger;
    private $security;

    public function __construct(TokenStorageInterface $security, LoggerInterface $logger)
    {
        $this->logger = $logger;
        $this->security = $security;
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        $user = $exception->getToken()->getUser();

        $this->logger->notice('Failed to login user: "'. $user. '"".  Reason: '. $exception->getMessage());
    }
}

但是当页面运行时,我遇到了:

身份验证失败处理程序没有返回响应。


你说你不能再返回响应了?不仅可以,而且必须要返回。 - iiirxs
我的意思是,显然(考虑到Symfony 2.4的代码),你以前只需要记录一些东西就可以了,现在你必须返回一个Response。编辑了这篇文章,使其更加清晰明了。 - Element Zero
日志记录后您希望发生什么?用户应该看到什么? - iiirxs
如果我没有实现那个处理程序,那么默认是什么?我的意思是,现在没有处理程序,它只会将它们抛回到登录页面,我使用 $error = $authenticationUtils->getLastAuthenticationError(); 检查登录错误并添加到闪存消息。 - Element Zero
基本上,我只想在登录失败时添加一些内容,而不是覆盖它。似乎在2.4中,您可以附加或覆盖它,现在它总是覆盖。基本上,这就是例如LogoutHandlerInterface和LogoutSuccessHandlerInterface之间的区别。 - Element Zero
1个回答

0

由于这是默认行为,因此您应该只重定向到登录页面。如果有特定要求,请根据需要进行修改。

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
...

private $flashBag;
private $logger;
private $security;

public function __construct(TokenStorageInterface $security, LoggerInterface $logger, FlashBagInterface $flashBag)
{
    $this->logger = $logger;
    $this->security = $security;
    $this->flashBag = $flashBag;
}

public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
    $user = $exception->getToken()->getUser();

    $this->logger->notice('Failed to login user: "'. $user. '"".  Reason: '. $exception->getMessage());

    $this->flashBag()->add('notice', 'Failed to login.');

    return new RedirectResponse('/login');
}

编辑: 添加了闪现消息


实际上,我发现了一个问题。如果我使用RedirectResponse进行重定向,它显然不会将异常传递给flash。我该如何将异常转发或者在该服务中调用flashbag? - Element Zero
1
是的,我也认为这就是我应该做的(在你回复之前我已经尝试过了),但是我得到了“无法自动装配服务'app.login.failure':方法'App\Security\LoginFailureLogger::__construct()'的参数'$session'引用类'Symfony\Component\HttpFoundation\Session\Session',但没有这样的服务存在。请尝试将类型提示更改为'Symfony\Component\HttpFoundation\Session\SessionInterface'。” - Element Zero
1
实际上,可以使用FlashBagInterface $flashBag而不是Session $session来完成这个操作,不知道你是否想更新你的答案耸肩。谢谢帮助! - Element Zero
已编辑以使用FlashBagInterface - iiirxs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接