如何在 Symfony 5.4 中创建不同的身份验证错误消息?

How to create different the authentication error message in Symfony 5.4?

默认情况下,它显示错误“无效凭据”。我已经看到类似“转到翻译,创建 security.en.yaml 并键入以下内容的答案:

# translations/security.en.yaml
'Invalid credentials.': 'Invalid email or password'

但是如何创建不同的错误呢?例如,密码错误时显示“密码无效”,电子邮件错误时显示“电子邮件不存在”。怎么做?

您必须创建自定义授权和例外。

示例: config/packages/security.yaml

security:
    enable_authenticator_manager: true
    ...
    providers: 
    ...
    firewalls:
        ...
        client:
            pattern: ^/
            custom_authenticators:
                - App\Security\ClientLoginFormAuthenticator
            logout:
                path: store.account.logout
                target: store.home
    access_control:
        ...

src/Security/ClientLoginFormAuthenticator.php

<?php
declare(strict_types=1);

namespace App\Security;

use App\Repository\UserRepository;
use App\Security\Exception\CustomException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use function in_array;

class ClientLoginFormAuthenticator extends AbstractLoginFormAuthenticator
{
    private const LOGIN_ROUTE = 'store.account.login';

    public function __construct(private UserRepository $userRepository, private UrlGeneratorInterface $urlGenerator)
    {}

    public function supports(Request $request): bool
    {
        return self::LOGIN_ROUTE === $request->attributes->get('_route')
            && $request->isMethod('POST');
    }

    public function authenticate(Request $request): Passport
    {
        $password = $request->request->get('_password');
        $username = $request->request->get('_username');
        $csrfToken = $request->request->get('_csrf_token');

        return new Passport(
            new UserBadge($username, function ($userIdentifier) {
                $user = $this->userRepository->findOneBy(['email' => $userIdentifier]);
                if ($user && in_array('ROLE_CLIENT', $user->getRoles(), true)) {
                    return $user;
                }

                //next condition
                if($user && $user->getEmail() === 'superadmin@example.com') {
                    throw new CustomException();
                }

                throw new BadCredentialsException(); //default exception
            }),
            new PasswordCredentials($password),
            [new CsrfTokenBadge('authenticate', $csrfToken)]
        );
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        return null;
    }

    protected function getLoginUrl(Request $request): string
    {
        return $this->urlGenerator->generate(self::LOGIN_ROUTE);
    }
}

src/Security/Exception/CustomException.php

<?php
namespace App\Security\Exception;

use Symfony\Component\Security\Core\Exception\AuthenticationException;

class CustomException extends AuthenticationException
{
    /**
     * {@inheritdoc}
     */
    public function getMessageKey()
    {
        return 'My Message.';
    }
}

对我有用! :) 祝你好运!