浏览器无法连接Spring Boot WebSocket(SockJS):跨域问题求助
嘿,这个WebSocket跨域的问题我之前也碰到过,咱们来搞定它!
问题根源
你看到的报错核心是:Spring Boot返回的Access-Control-Allow-Origin头值不对,它返回了http://localhost:8080/ws/info,但浏览器期望的是允许你的React应用所在的http://localhost:3000源,这就触发了同源策略的限制。
解决方案:调整Spring Boot的WebSocket配置
既然你已经创建了WebSocketMessageBrokerConfigurer的实现类,咱们直接修改它的CORS设置就行。下面是完整的配置示例,重点看registerStompEndpoints方法里的设置:
import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { // 配置消息代理,这里用简单内存代理,生产环境可以换RabbitMQ之类的 config.enableSimpleBroker("/topic"); // 设置应用前缀,前端发消息要以/app开头 config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { // 注册WebSocket端点,关键是这里的CORS设置 registry.addEndpoint("/ws") // 明确允许React应用的源,新版本Spring Boot推荐用setAllowedOriginPatterns .setAllowedOriginPatterns("http://localhost:3000") // 启用SockJS,兼容不支持原生WebSocket的浏览器 .withSockJS(); } }
几个关键细节:
- 别图省事用
setAllowedOrigins("*"),虽然能解决问题,但生产环境太不安全,明确指定你的前端地址更稳妥 - 如果你的Spring Boot版本低于2.4,可能需要用
setAllowedOrigins("http://localhost:3000")代替setAllowedOriginPatterns,不过尽量升级到新版本 - 确保端点路径
/ws和你前端连接的路径完全一致
前端React连接代码检查
再确认下你的前端连接代码是不是正确指向了Spring Boot的WebSocket端点:
import SockJS from 'sockjs-client'; import Stomp from 'stompjs'; const connectToWebSocket = () => { // 这里的地址要和后端配置的端点一致 const socket = new SockJS('http://localhost:8080/ws'); const stompClient = Stomp.over(socket); stompClient.connect({}, (frame) => { console.log('成功连接到WebSocket:', frame); // 订阅消息主题,比如/topic/your-topic stompClient.subscribe('/topic/messages', (message) => { console.log('收到消息:', message.body); }); }, (error) => { console.error('连接失败:', error); }); };
额外注意事项(如果用了Spring Security)
要是你的项目加了Spring Security,还得在安全配置里放行WebSocket的路径,否则会被拦截:
import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() // 放行WebSocket相关的所有请求 .antMatchers("/ws/**", "/ws/info/**").permitAll() .anyRequest().authenticated(); } }
最后,重启你的Spring Boot服务器和React应用,清除浏览器缓存后再测试,应该就能正常建立WebSocket连接了!
内容的提问来源于stack exchange,提问作者alex




