You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring MVC 3.X升级5.X后Security致登录页返回空200响应求助

问题分析与解决方案

从你的描述来看,升级到Spring 5.x后引入Spring Security过滤器链导致登录页返回200但内容为空,核心问题大概率出在Spring Security过滤器的上下文绑定或者自定义CompositeFilter的请求传递逻辑上,结合你的代码给出几个排查和修复方向:

1. 修正DelegatingFilterProxy的上下文属性配置

你当前给DelegatingFilterProxy设置的contextAttribute是DispatcherServlet的上下文属性:

delegatingFilterProxy.setContextAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher");

但Spring Security的springSecurityFilterChain是定义在根Spring上下文(由ContextLoaderListener加载)中的,而不是DispatcherServlet的子上下文。在Spring 5.x中,这个上下文绑定的要求更严格,你需要把这个属性去掉,让DelegatingFilterProxy默认从根上下文获取过滤器:

修改代码如下:

DelegatingFilterProxy delegatingFilterProxy = container.createFilter(DelegatingFilterProxy.class);
delegatingFilterProxy.setServletContext(container);
// 移除下面这行错误的上下文属性配置
// delegatingFilterProxy.setContextAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher");
container.addFilter("springSecurityFilterChain", delegatingFilterProxy).addMappingForUrlPatterns(null, false, "/*");

2. 检查自定义CompositeFilter的过滤器实现

你的securityFilters是CompositeFilter,包含sqlInjectionCheckFilter和hostCheckFilter,需要确保这两个自定义过滤器正确调用了FilterChain.doFilter(request, response)。在Spring 5.x中,过滤器如果没有继续传递请求链,会导致响应被截断,返回空内容。

比如你的自定义过滤器应该遵循这个模板:

public class SqlInjectionCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 你的校验逻辑
        // 必须调用这行,否则请求不会继续往下传递到后续过滤器/控制器
        chain.doFilter(request, response);
    }

    // 其他初始化、销毁方法...
}

如果你的旧版本过滤器里遗漏了这行,升级后Spring Security的过滤器链会因为请求被中断而无法渲染登录页。

3. 分离根上下文与DispatcherServlet上下文(推荐最佳实践)

你当前把所有配置文件(包括Spring Security、Spring MVC的)都放到了同一个XmlWebApplicationContext里,由ContextLoaderListener和DispatcherServlet共用。这在Spring 3.x可能没问题,但Spring 5.x更推荐分离:

  • 根上下文(ContextLoaderListener)加载:applicationContext.xml、spring-security-db.xml(业务、安全相关配置)
  • DispatcherServlet上下文加载:dispatcher-servlet.xml、doc-views.xml(MVC、视图相关配置)

修改你的onStartup方法:

@Override
public void onStartup(ServletContext container) throws ServletException {
    // 根上下文:加载安全、业务配置
    XmlWebApplicationContext rootContext = new XmlWebApplicationContext();
    rootContext.setConfigLocations("/WEB-INF/****/applicationContext.xml","/WEB-INF/*****/spring-security-db.xml");
    container.addListener(new ContextLoaderListener(rootContext));

    // MVC上下文:加载MVC、视图配置
    XmlWebApplicationContext dispatcherContext = new XmlWebApplicationContext();
    dispatcherContext.setConfigLocations("/WEB-INF/***/dispatcher-servlet.xml","/WEB-INF/***/doc-views.xml");
    dispatcherContext.setParent(rootContext); // 设置父上下文为根上下文

    container.addListener(new HttpSessionEventPublisher());
    container.addListener(new DriverRegistrationListener());

    // Spring Security过滤器:默认从根上下文获取chain
    DelegatingFilterProxy delegatingFilterProxy = container.createFilter(DelegatingFilterProxy.class);
    container.addFilter("springSecurityFilterChain", delegatingFilterProxy).addMappingForUrlPatterns(null, false, "/*");

    ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("/");

    initalizeLog4j(container);
}

这种分离方式能避免上下文混淆,减少Spring 5.x中因为上下文边界严格导致的问题。

4. 验证Spring Security登录页的权限配置

确保你的Spring Security配置中,登录页路径是允许匿名访问的,比如:

<security:http auto-config="true" use-expressions="true">
    <!-- 允许登录页匿名访问 -->
    <security:intercept-url pattern="/login" access="permitAll()"/>
    <!-- 其他权限配置 -->
    <security:form-login login-page="/login" />
    <!-- 你的自定义过滤器配置 -->
    <security:custom-filter after="BASIC_AUTH_FILTER" ref="securityFilters" />
</security:http>

如果登录页被拦截,Spring Security可能会返回空响应而不是重定向/渲染页面。

按照上面的步骤排查,应该能解决登录页返回空内容的问题。

内容的提问来源于stack exchange,提问作者guru mani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:59:03