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

Jetty 11配置SSL加密WebSocket服务器及端口复用问题求助

问题分析与解决方案

问题1:正确为WebSocket启用SSL

你的代码出现双端口、SSL端口随机分配的核心原因是**new Server(port_)会自动创建一个默认HTTP连接器**,同时手动添加的SSL连接器未指定端口,导致Jetty随机分配端口。要正确启用SSL,需按以下步骤修改:

  1. 创建不带端口的Server实例,避免自动生成默认HTTP连接器
  2. 手动创建SSL连接器并指定目标端口
  3. 确保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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 16:23:18