Spring MVC非Boot环境下AuthenticationSuccessEventListener如何获取HttpServletRequest
问题根因
- 代码调用位置错误:你将
RequestContextHolder.getRequestAttributes()写在了类成员变量初始化阶段,该阶段无绑定的Web请求,不可能拿到请求对象。即使将代码移入onApplicationEvent方法,也会因为下面的配置缺失问题报错。 - Spring MVC默认仅在
DispatcherServlet的请求处理流程中自动绑定请求到线程上下文,而AuthenticationSuccessEvent是Spring Security过滤器链在请求进入DispatcherServlet之前发布的,此时还没有完成请求上下文的绑定。 - 未配置请求上下文暴露组件:你没有注册
RequestContextListener或RequestContextFilter,非DispatcherServlet处理的请求链路无法通过RequestContextHolder获取请求对象。
解决方案
步骤1:注册RequestContextListener
如果是web.xml配置的项目,添加如下监听器配置:
<listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>
如果是注解驱动的无web.xml项目,在你的WebApplicationInitializer实现类的onStartup方法中添加监听器注册:
@Override public void onStartup(ServletContext servletContext) throws ServletException { servletContext.addListener(new RequestContextListener()); // 保留原有其他配置逻辑 }
该监听器会在所有请求进入处理链路的最开始,就将当前请求绑定到线程上下文,供后续全链路获取。
步骤2:调整获取请求的代码位置
将请求获取逻辑移入onApplicationEvent方法内部,修改后的代码如下:
@Component public class AuthenticationSuccessEventListener implements ApplicationListener<AuthenticationSuccessEvent> { @Override public void onApplicationEvent(AuthenticationSuccessEvent event) { ServletRequestAttributes requestAttr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (requestAttr != null) { HttpServletRequest request = requestAttr.getRequest(); // 此处即可正常操作request对象 } } }
注意事项
- 该方案仅适用于同步请求场景,如果你的认证流程是异步处理的,请求上下文不会自动传递到异步线程,需要自行处理上下文传递。
- 你给出的示例代码中类名与监听事件不匹配(类名是AuthenticationFailureListener却监听AuthenticationSuccessEvent),注意根据实际业务修正类名。
内容的提问来源于stack exchange,提问作者zvzvzxvzxv
相关产品推荐
相关产品推荐

