Jetty 11配置SSL加密WebSocket服务器及端口复用问题求助
问题分析与解决方案
问题1:正确为WebSocket启用SSL
你的代码出现双端口、SSL端口随机分配的核心原因是**new Server(port_)会自动创建一个默认HTTP连接器**,同时手动添加的SSL连接器未指定端口,导致Jetty随机分配端口。要正确启用SSL,需按以下步骤修改:
- 创建不带端口的
Server实例,避免自动生成默认HTTP连接器 - 手动创建SSL连接器并指定目标端口
- 确保WebSocket Servlet上下文绑定到唯一的SSL连接器
修改后的完整代码:
public class Test { public Test(int port, SSLContext sslContext) { port_ = port; // 创建无端口Server,避免自动生成默认HTTP连接器 server_ = new Server(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setSslContext(sslContext); // 可选:若需支持HTTP/2下的WebSocket,开启ALPN // sslContextFactory.setEnableALPN(true); // 配置HTTPS的HttpConfiguration HttpConfiguration httpsConfig = new HttpConfiguration(); httpsConfig.addCustomizer(new SecureRequestCustomizer()); // 创建SSL连接器并指定端口,避免随机分配 connector_ = new ServerConnector(server_, new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), new HttpConnectionFactory(httpsConfig)); connector_.setPort(port_); server_.addConnector(connector_); // 配置WebSocket Servlet var servlet = new JettyWebSocketServlet() { @Override protected void configure(JettyWebSocketServletFactory factory) { factory.addMapping("/", (req, res) -> new WebSocketHandler()); } }; var handler = new ServletContextHandler(); handler.addServlet(new ServletHolder(servlet), "/"); // 初始化WebSocket容器,必填步骤 JettyWebSocketServletContainerInitializer.configure(handler, (context, configurator) -> { // 可在此配置WebSocket参数,如最大消息大小 configurator.setMaxTextMessageSize(65536); }); server_.setHandler(handler); } public void start() { try { server_.start(); System.out.println("SSL WebSocket Server started at wss://0.0.0.0:" + connector_.getLocalPort()); server_.join(); } catch (Exception ex) { ex.printStackTrace(); // 不要吞异常,便于排查问题 } } private int port_; private Server server_; private ServerConnector connector_; }
注意:客户端必须使用wss://协议连接(例如wss://your-host:指定端口/),而非ws://。
问题2:让WebSocket与HTTP共用一个端口
上述修改已经实现了端口共用:
- 唯一的SSL连接器同时支持HTTPS(普通HTTP请求)和WSS(WebSocket over SSL),客户端通过同一个端口:
- 用
https://访问普通HTTP服务 - 用
wss://发起WebSocket连接
- 用
- 若不需要HTTP服务,仅保留WebSocket的Servlet映射即可,不影响WebSocket正常运行
如果必须在同一端口同时支持非SSL的HTTP和SSL的HTTPS/WSS,可使用NegotiatingServerConnector实现协议协商,但会增加复杂度,测试场景不推荐。
额外排查点(若仍有SSL握手错误)
- 确认客户端使用
wss://协议,而非ws:// - 检查SSLContext中的证书是否包含正确的SAN(Subject Alternative Name),且客户端信任该证书
- 添加JVM调试参数
-Djavax.net.debug=ssl,handshake,查看握手失败的具体原因
内容的提问来源于stack exchange,提问作者IronHawk
相关产品推荐
相关产品推荐

