如何使用 Jetty 11 设置安全的 Websocket 服务器

How to setup secure Websocket server using Jetty 11

提问人:IronHawk 提问时间:6/20/2023 更新时间:6/20/2023 访问量:229

问:

我是 Jetty 的新手,想创建一个带有 SSL 的小型测试 Websocket 服务器(使用 Jetty 11)。 找到许多基于 Jetty 9 的示例,但没有 Jetty 11 的示例。

我的测试代码如下所示:

public class Test {
    public Test(int port, SSLContext sslContext) {
        port_ = port;

        server_ = new Server(port_);

        SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
        sslContextFactory.setSslContext(sslContext);

        HttpConfiguration httpsConfig = new HttpConfiguration();
        httpsConfig.addCustomizer(new SecureRequestCustomizer());

        connector_ = new ServerConnector(server_,
            new SslConnectionFactory(sslContextFactory,  HttpVersion.HTTP_1_1.asString()),
            new HttpConnectionFactory(httpsConfig));
        server_.addConnector(connector_);

        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), "/");
        JettyWebSocketServletContainerInitializer.configure(handler, (context, configurator) ->
        {
        });

        server_.setHandler(handler);
    }

    public void start() {
        try {
            server_.start();
            System.out.println("Server started at port " + connector_.getLocalPort());

            server_.join();
        } catch(Exception ex) {

        }
    }

    private int port_;
    private Server server_;
    private ServerConnector connector_;
}

传递给构造函数的 SSL 上下文通过密钥库等进行初始化。 但是当我尝试连接到此服务器时,我在客户端收到“SSL握手错误”。如果我使用另一个 Websocket 服务器,我的客户端可以使用相同的证书和 co 正常工作。

在运行服务器时,我在日志中看到以下内容:

[main] INFO org.eclipse.jetty.server.Server - jetty-11.0.15; built: 2023-04-11T18:37:53.775Z; git: 5bc5e562c8d05c5862505aebe5cf83a61bdbcb96; jvm 17.0.1+12-LTS-39
[main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@7f3b84b8{/,null,AVAILABLE}
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@5f3a4b84{HTTP/1.1, (http/1.1)}{0.0.0.0:12345}
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@149494d8{SSL, (ssl, http/1.1)}{0.0.0.0:52376}
[main] INFO org.eclipse.jetty.server.Server - Started Server@5af97850{STARTING}[11.0.15,sto=0] @3110ms
Server started at port 52376

因此,Websocket servlet 似乎正在运行端口 12345,但未为其启用 SSL。从另一端来看,HTTP 连接器具有 SSL。我怀疑我错过了一些重要的东西。

所以我的问题是:

  • 如何为 Websocket proprly om Jetty 11 启用 SSL?
  • 如何防止对 HTTP 使用随机端口,同时对 HTTP 和 Websocket 使用单个侦听器端口?(实际上我只需要HTTP来打开Websocket)

提前致谢!

Java SSL WebSocket Jetty 服务器端

评论


答:

2赞 Lachlan 6/20/2023 #1

您正在配置两个连接器。

正在添加 one,您在输出中看到 .server_ = new Server(port_);Started ServerConnector@5f3a4b84{HTTP/1.1, (http/1.1)}{0.0.0.0:12345}

另一个配置为您在输出中看到的 .connector_ = new ServerConnector(...Started ServerConnector@149494d8{SSL, (ssl, http/1.1)}{0.0.0.0:52376}

因此,在不指定端口的情况下创建服务器,例如 ,然后在配置了 的连接器上设置端口。server_ = new Server();connector_.setPort(port_)

评论

1赞 IronHawk 6/20/2023
你好拉克兰!谢谢你的回答。您是对的:应在连接器中指定端口。通过更改此设置,我在日志中只看到一个连接器。伟大!在此更改之后,我的客户端能够正确连接。我还注意到,要对客户端进行身份验证,必须添加以下调用:sslContextFactory.setNeedClientAuth(true);