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

SpringBoot3添加自定义Filter后WebSocket连接报401错误求助

问题描述

服务在SpringBoot 2.6(内置SpringFramework 5)下运行正常,但升级到SpringBoot 3.2.4(内置SpringFramework 6)后,WebSocket服务器无法连接,客户端提示:Error: Unexpected server response: 401。

排查过程:搭建简单测试项目逐步验证,创建WebSocket配置与处理器、多端口配置、WebSocket拦截器与HTTP过滤器均正常,直到添加自定义Filter注册配置后,WebSocket连接开始报401错误。

相关代码

1. SecurityConfig

@Configuration
public class SecurityConfig  {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests((requests) -> requests
                    .anyRequest().permitAll()
            ).httpBasic(withDefaults());

    return http.build();
}
}

2. WebSocketConfig

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(testingHandler(), "/ws/{id}").setAllowedOrigins("*")
                .addInterceptors(handshakeInterceptor());
    }

    @Bean
    public WebSocketHandler testingHandler() {
        return new TestingHandler();
    }

    @Bean
    public HandshakeInterceptor handshakeInterceptor() {
        return new TestingInterceptor();
    }

    @Bean
    public ServletServerContainerFactoryBean createWebSocketContainer() {
        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
        container.setMaxTextMessageBufferSize(WEB_SOCKET_BUFFER_SIZE);
        container.setMaxBinaryMessageBufferSize(WEB_SOCKET_BUFFER_SIZE);
        return container;
    }
}

3. ServerConfig(多端口配置)

@Configuration
public class ServerConfig {


    @Value("${server.additionalPorts}")
    private String additionalPorts;

    /**
     * 多端口配置
     */
    @Bean
    public TomcatServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        Connector[] additionalConnectors = this.additionalConnector();
        if (additionalConnectors != null && additionalConnectors.length > 0) {
            tomcat.addAdditionalTomcatConnectors(additionalConnectors);
        }
        //Invalid character error
        tomcat.addConnectorCustomizers(new TomcatConnectorCustomizer() {
            @Override
            public void customize(Connector connector) {
                connector.setProperty("relaxedQueryChars", "|{}[]");
            }
        });
        return tomcat;
    }

    private Connector[] additionalConnector() {
        if (!StringUtils.hasLength(this.additionalPorts)) {
            return null;
        }
        String[] ports = this.additionalPorts.split(",");
        List<Connector> result = new ArrayList<>();
        for (String port : ports) {
            Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
            connector.setScheme("http");
            connector.setProperty("relaxedQueryChars", "|{}[]");
            connector.setPort(Integer.valueOf(port));
            result.add(connector);
        }
        return result.toArray(new Connector[] {});
    }
}

4. WebMvcConfig(Filter注册)

@Configuration
public class WebMvcConfig{

    @Bean
    public Filter testingFilter(){
        return new TestingFilter();
    }
    @Bean
    public FilterRegistrationBean<DelegatingFilterProxy> filterRegist() {
        FilterRegistrationBean<DelegatingFilterProxy> registration = new FilterRegistrationBean();
        registration.setFilter(new DelegatingFilterProxy("testingFilter"));
        registration.addUrlPatterns("/rest/*");//URI路径过滤
        registration.setOrder(1);
        return registration;
    }
}

(注:Filter、Interceptor、WebSocket处理器均为仅含空方法的测试代码)

问题原因与解决方案

核心原因

SpringBoot 3.x(基于Spring Framework 6)中,FilterRegistrationBean的asyncSupported默认值从true改为false。WebSocket握手依赖HTTP Upgrade异步请求,不支持异步的Filter会阻断握手流程,最终返回401错误。同时你使用DelegatingFilterProxy的注册方式存在冗余,未明确开启异步支持,进一步触发了该问题。

解决方案

方案一:修改现有Filter注册,添加异步支持

调整WebMvcConfig中的filterRegist方法,增加异步支持配置:

@Bean
public FilterRegistrationBean<DelegatingFilterProxy> filterRegist() {
    FilterRegistrationBean<DelegatingFilterProxy> registration = new FilterRegistrationBean();
    registration.setFilter(new DelegatingFilterProxy("testingFilter"));
    registration.addUrlPatterns("/rest/*");
    registration.setOrder(1);
    registration.setAsyncSupported(true); // 开启异步支持
    return registration;
}

方案二:简化Filter注册(推荐)

直接注册TestingFilter的FilterRegistrationBean,无需使用DelegatingFilterProxy,同时开启异步支持:

@Configuration
public class WebMvcConfig{

    @Bean
    public TestingFilter testingFilter(){
        return new TestingFilter();
    }

    @Bean
    public FilterRegistrationBean<TestingFilter> filterRegist(TestingFilter testingFilter) {
        FilterRegistrationBean<TestingFilter> registration = new FilterRegistrationBean<>(testingFilter);
        registration.addUrlPatterns("/rest/*");
        registration.setOrder(1);
        registration.setAsyncSupported(true);
        return registration;
    }
}

补充说明

WebSocket握手请求属于异步处理场景,所有可能拦截该请求路径的Filter都必须开启异步支持(asyncSupported=true),否则会导致握手失败。SpringBoot 2.x与3.x在此配置上的默认值差异是引发兼容性问题的关键。

内容的提问来源于stack exchange,提问作者iyaya lc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 17:37:08