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

Spring Boot中通过STOMP连接WebSocket时如何解决CORS错误?

解决Spring Boot WebSocket(SockJS)的CORS错误

问题分析

你遇到的CORS错误源于SockJS初始化时发送的/ws/chat/info HTTP请求被Spring Security拦截,而你的Security配置直接禁用了CORS功能,导致该请求无法返回Access-Control-Allow-Origin响应头。尽管StompEndpoint配置了允许的源,但仅对WebSocket握手请求生效,无法覆盖SockJS的前置HTTP请求。

修复步骤

1. 修改Spring Security配置,启用并正确配置CORS

移除SecurityConfig中禁用CORS的代码,替换为自定义CORS配置,确保允许前端源、自定义请求头(如你的Authorization头):

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
            .csrf(AbstractHttpConfigurer::disable)
            // 启用CORS并使用自定义配置源
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            .authorizeHttpRequests(authorize -> authorize
                    .requestMatchers("/user/**", "/ws/chat/**").permitAll()
                    // 允许SockJS的info请求和WebSocket握手请求无需认证
                    .anyRequest().authenticated()
            )
            .authenticationProvider(authenticationProvider)
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
    return http.build();
}

// 配置CORS允许的源、头和方法
@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    // 允许你的前端源
    configuration.setAllowedOrigins(Collections.singletonList("http://localhost:5501"));
    // 允许所有请求方法
    configuration.setAllowedMethods(Collections.singletonList("*"));
    // 允许自定义头(包括Authorization)
    configuration.setAllowedHeaders(Collections.singletonList("*"));
    // 允许携带凭证(如果需要)
    configuration.setAllowCredentials(true);
    
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    // 对所有路径应用CORS配置
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

2. 调整StompEndpoint配置(保持一致性)

将Stomp的允许源配置与Security保持一致,或使用setAllowedOriginPatterns适配更灵活的场景:

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
    // 和Security的CORS配置保持一致
    registry.addEndpoint("/ws/chat")
            .setAllowedOrigins("http://localhost:5501")
            .withSockJS();
    // 若需匹配localhost任意端口,可改用:
    // .setAllowedOriginPatterns("http://localhost:*")
}

3. 客户端请求优化(可选)

如果需要携带凭证,可在SockJS配置中添加withCredentials: true:

var socket = new SockJS('http://localhost:8080/ws/chat', null, {
    headers: {
        Authorization: 'Bearer ' + jwt
    },
    withCredentials: true
});
stompClient = Stomp.over(socket);
stompClient.connect({}, onConnected, onError);

关键注意点

  • SockJS的/info初始化请求是普通HTTP请求,会经过Spring Security过滤器链,必须在Security中配置CORS,不能仅依赖Stomp的配置。
  • 若启用凭证携带,需确保前后端配置一致(后端setAllowCredentials(true),前端withCredentials: true)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 11:33:33