Java中为WebSocket握手响应添加CORS头部的实现方案
WebSocket跨域CORS问题解决方案(Tyrus服务器)
问题背景
浏览器端JS应用连接基于Tyrus运行的WebSocket服务时,出现GET has been blocked by CORS policy错误。现有启动代码如下:
public static void main(String[] args) { int port = Integer.parseInt(args[0]); final Server server = new Server("0.0.0.0", port, "/", null, LiveWebSocket.class); try { server.start(); System.out.println("WebSocketServer started on port " + port); } catch (final DeploymentException e) { throw new RuntimeException("Failed to start WebSocketServer", e); } try { Thread.currentThread().join(); } catch (InterruptedException e) { throw new RuntimeException(e); } }
已实现CORS过滤器并注册到ResourceConfig,但不知道如何将配置集成到main方法的服务器启动流程中:
@Provider public class CorsFilter implements ContainerResponseFilter { @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) { responseContext.getHeaders().add("Access-Control-Allow-Origin", "*"); responseContext.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization"); responseContext.getHeaders().add("Access-Control-Allow-Credentials", "true"); responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); responseContext.getHeaders().add("Access-Control-Max-Age", "1209600"); } }
final ResourceConfig config = new ResourceConfig(); config.register(CorsFilter.class); config.register(LiveWebSocket.class);
解决方案
方案1:通过ServerConfig集成ResourceConfig
Tyrus的Server类支持传入ServerConfig对象加载自定义配置,只需修改main方法的服务器初始化逻辑:
public static void main(String[] args) { int port = Integer.parseInt(args[0]); // 初始化配置并注册过滤器与WebSocket端点 final ResourceConfig config = new ResourceConfig(); config.register(CorsFilter.class); config.register(LiveWebSocket.class); // 将ResourceConfig转换为ServerConfig final ServerConfig serverConfig = ServerConfig.Builder.create().resourceConfig(config).build(); // 使用带ServerConfig的构造函数创建服务器 final Server server = new Server("0.0.0.0", port, "/", serverConfig); try { server.start(); System.out.println("WebSocketServer started on port " + port); } catch (final DeploymentException e) { throw new RuntimeException("Failed to start WebSocketServer", e); } try { Thread.currentThread().join(); } catch (InterruptedException e) { throw new RuntimeException(e); } }
此方法会让CORS过滤器作用于所有HTTP请求(包括WebSocket握手请求),解决跨域问题。
方案2:直接添加WebSocket握手拦截器
如果方案1不生效,可以直接针对WebSocket握手阶段添加拦截器,更精准处理跨域:
- 实现握手拦截器:
import java.util.Collections; import javax.websocket.HandshakeRequest; import javax.websocket.HandshakeResponse; import javax.websocket.server.ServerEndpointConfig; public class CorsHandshakeInterceptor implements ServerEndpointConfig.Configurator { @Override public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { response.getHeaders().put("Access-Control-Allow-Origin", Collections.singletonList("*")); response.getHeaders().put("Access-Control-Allow-Credentials", Collections.singletonList("true")); // 按需添加其他CORS头部,如Access-Control-Allow-Headers等 } }
- 在WebSocket端点类上配置该拦截器:
import javax.websocket.ServerEndpoint; @ServerEndpoint(value = "/your-websocket-path", configurator = CorsHandshakeInterceptor.class) public class LiveWebSocket { // 你的WebSocket业务逻辑 }
这种方式直接修改握手响应头,确保跨域规则被应用到WebSocket连接的初始请求上。
内容的提问来源于stack exchange,提问作者Mirey Mackey
相关产品推荐
相关产品推荐

