Symfony5.3如何自定义认证错误并显示CustomUserMessageAuthenticationException信息
问题原因
你当前的写法存在两处核心错误:
- 直接修改Symfony核心的
AbstractLoginFormAuthenticator类,不符合开发规范,后续框架升级会直接覆盖你的修改 - 在
onAuthenticationFailure方法中直接抛出CustomUserMessageAuthenticationException,会中断正常的错误存储、重定向流程,导致错误信息没有写入session,所以getLastAuthenticationError()无法读取到自定义内容
解决步骤
1. 创建自定义认证器子类
不要修改框架核心类,在src/Security目录下新建LoginFormAuthenticator.php,继承AbstractLoginFormAuthenticator,重写所需方法,示例代码如下:
<?php namespace App\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException; use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator; class LoginFormAuthenticator extends AbstractLoginFormAuthenticator { private $router; public function __construct(UrlGeneratorInterface $router) { $this->router = $router; } // 实现抽象方法getLoginUrl,返回登录页路由 protected function getLoginUrl(Request $request): string { return $this->router->generate('app_login'); } // 重写onAuthenticationFailure方法 public function onAuthenticationFailure(Request $request, AuthenticationException $exception): RedirectResponse { if ($request->hasSession()) { // 自定义异常内容,支持根据原异常类型返回不同提示 $customException = new CustomUserMessageAuthenticationException('账号或密码错误,请重试'); // 将自定义异常存入session $request->getSession()->set(Security::AUTHENTICATION_ERROR, $customException); } return new RedirectResponse($this->getLoginUrl($request)); } // 其他必要方法比如authenticate、onAuthenticationSuccess等按你原有业务逻辑实现即可 }
2. 配置安全组件使用自定义认证器
修改config/packages/security.yaml,在你使用的防火墙下配置自定义认证器:
security: firewalls: main: # 其他原有配置保持不变 custom_authenticators: - App\Security\LoginFormAuthenticator
3. 前端展示
你现有的SecurityController和Twig登录模板不需要做任何修改,getLastAuthenticationError()会自动读取session中存储的自定义异常,渲染到前端页面。
如果需要翻译自定义错误提示,只需在translations/security.zh_CN.yaml中添加对应翻译项即可。
内容的提问来源于stack exchange,提问作者Zip120
相关产品推荐
相关产品推荐

