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
相关产品推荐
相关产品推荐

