首页 > 解决方案 > Symfony 4 在登录失败时检索用户的电子邮件

问题描述

我创建了一个事件侦听器,以在用户登录尝试失败但无法获取与请求关联的用户名(在本例中为用户的电子邮件)时增加失败的登录计数。

class LoginFailureListener
{
    private $requestStack;
    private $entityManager;

    public function __construct(RequestStack $requestStack, EntityManagerInterface $entityManager)
    {
        $this->requestStack = $requestStack;
        $this->entityManager = $entityManager;
    }

    public function onAuthenticationFailure(AuthenticationFailureEvent $event)
    {   
        $email = $event->getAuthenticationToken()->getUsername();
        dump($email);

$email 的值是一个空字符串...我见过其他示例,其中 getUsername() 似乎返回了预期值。

在我的用户模型中,我定义了以下内容:

/**
 * @see UserInterface
 */
public function getUsername(): string
{
    return (string) $this->email;
}

安全.yaml:

 providers:
        app_user_provider:
            entity:
                class: App\Entity\User
                property: email
firewalls:
        main:
            anonymous: true
            guard:
                authenticators:
                    - App\Security\LoginFormAuthenticator
            form_login:
                login_path: login
                check_path: login
                username_parameter: "email"
                password_parameter: "password"

我是否需要在其他地方配置 getUsername 以便它返回用户的标识符(电子邮件)?

以下产生了所需的信息:

$email = $event->getAuthenticationToken()->getCredentials()['email'];

标签: phpsymfony

解决方案


没有其他地方必须配置 getUsername(),而是在您的实体中 - 这似乎没问题。

我的建议(以及 200 美元的赌注)是可能没有 authenticationToken,因为正是用户未能输入有效凭据。但是,即使是匿名用户也有会话令牌,所以你可以试试这个:

在侦听器的构造函数中注入 ContainerInterface $container,然后尝试

$token = $this->container->get('security.token_storage')->getToken();
$user = $token->getUser();
$email = $this->container->get('session')->get('_security.last_username');
dump($token, $user, $email);

如果没有电子邮件,则可能是因为在登录尝试后没有在会话中设置它。Symfony 通常在登录后立即执行此操作,使用任何扩展 AbstractFormLoginAuthenticator 的类,在方法 getCredentials()

$request->getSession()->set(
            Security::LAST_USERNAME,
            $credentials['email']
        );

请参阅https://symfony.com/doc/current/security/form_login_setup.html

希望这可以帮助你交配。祝你好运。

编辑:您的 security.yaml 似乎也不错,但请确保您已根据以下准则在下面定义您的表单登录:

            form_login:
                login_path: login # or whatever your path is
                check_path: login # or whatever your path is
                username_parameter: login[email] # these fields need to be as they appear in the html form
                password_parameter: login[password]
                default_target_path: index # or whatever your path is
            provider: app_user_provider

推荐阅读