如何排查Spring Session中的非序列化对象?
找出Spring Session中非序列化对象的方法及问题解决
一、定位非序列化对象的实用方法
- 直接从异常栈获取信息:你提供的异常日志已经明确指出
org.springframework.security.web.servletapi.HttpServlet3RequestFactory$Servlet3SecurityContextHolderAwareRequestWrapper未实现Serializable接口,这是最直接的定位方式。如果异常未直接显示目标对象,可尝试以下方法: - 手动序列化测试:在代码中对Session中的属性逐个进行序列化测试,捕获
NotSerializableException来定位具体对象。示例代码:
HttpSession session = request.getSession(); Enumeration<String> attributeNames = session.getAttributeNames(); while (attributeNames.hasMoreElements()) { String name = attributeNames.nextElement(); Object value = session.getAttribute(name); try { org.apache.commons.lang3.SerializationUtils.serialize(value); } catch (org.apache.commons.lang3.SerializationException e) { System.err.println("非序列化对象:" + name + ",类型:" + value.getClass().getName()); e.printStackTrace(); } }
- 调试模式分析Session结构:在调试状态下查看
HttpSession的属性列表,逐一检查每个属性的类是否实现了Serializable接口,尤其注意嵌套对象(如集合元素、对象成员变量)是否符合序列化要求。
二、针对当前问题的解决思路
你的问题核心是Spring Security的Servlet3SecurityContextHolderAwareRequestWrapper被存入了Session,而该类本身不支持序列化,可通过以下方式解决:
- 禁止将Request对象存入Session:排查代码中是否存在将
HttpServletRequest或其包装类放入Session的逻辑,这类对象本身不应被持久化,及时移除相关代码。 - 调整Spring Security会话策略:通过配置限制Session中存储的内容,避免请求相关对象被存入Session。示例配置:
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .maximumSessions(1) .and() .csrf().disable(); } }
- 会话持久化前清理冗余属性:在拦截器或过滤器中手动移除Session中的非序列化属性,示例代码:
public class SessionCleanupFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = ((HttpServletRequest) request).getSession(false); if (session != null) { Enumeration<String> attrNames = session.getAttributeNames(); while (attrNames.hasMoreElements()) { String name = attrNames.nextElement(); Object attr = session.getAttribute(name); if (attr instanceof HttpServletRequest || attr.getClass().getName().contains("SecurityContextHolderAwareRequestWrapper")) { session.removeAttribute(name); } } } chain.doFilter(request, response); } }
内容的提问来源于stack exchange,提问作者Tusker
相关产品推荐
相关产品推荐

