使用Jetty和JavaScript客户端设置安全的WebSocket服务器

Ste*_*ich 2 javascript java ssl websocket

我正在尝试使用Jetty设置安全的WebSocket服务器,如下所示:

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.server.WebSocketHandler;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;


public class WebSocketServer
{
    private Server server;
    private String host="localhost";
    private int port=8080;
    private String keyStorePath = "C:\\keystore";
    private String keyStorePassword="password";
    private String keyManagerPassword="password";
    private List<Handler> webSocketHandlerList = new ArrayList();
    MessageHandler messagehandler;

    public WebSocketServer()
    {
        System.out.println("WebSocketServer");

        server = new Server();

        // connector configuration
        SslContextFactory sslContextFactory = new SslContextFactory();
        sslContextFactory.setKeyStorePath(keyStorePath);
        sslContextFactory.setKeyStorePassword(keyStorePassword);
        sslContextFactory.setKeyManagerPassword(keyManagerPassword);
        SslConnectionFactory sslConnectionFactory = new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString());
        HttpConnectionFactory httpConnectionFactory = new HttpConnectionFactory(new HttpConfiguration());
        ServerConnector sslConnector = new ServerConnector(server, sslConnectionFactory, httpConnectionFactory);
        sslConnector.setHost(host);
        sslConnector.setPort(port);
        server.addConnector(sslConnector);

        // handler configuration
        HandlerCollection handlerCollection = new HandlerCollection();
        handlerCollection.setHandlers(webSocketHandlerList.toArray(new Handler[0]));
        server.setHandler(handlerCollection);

        WebSocketHandler wsHandler = new WebSocketHandler() {
            @Override
            public void configure(WebSocketServletFactory webSocketServletFactory) {
                webSocketServletFactory.register(MyWebSocketHandler.class);
            }
        };
        ContextHandler wsContextHandler = new ContextHandler();
        wsContextHandler.setHandler(wsHandler);
        wsContextHandler.setContextPath("/");  // this context path doesn't work ftm
        webSocketHandlerList.add(wsHandler);

        messagehandler = new MessageHandler();
        new Thread(messagehandler).start();

        try {
            server.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

密钥库文件与发现以下命令创建这里在JDK/bin文件夹:

keytool.exe -keystore keystore -alias jetty -genkey -keyalg RSA
Run Code Online (Sandbox Code Playgroud)

之后,我将文件移动到C目录中以便于路径使用.

使用此配置,我的服务器似乎没有任何问题.所以我试图用我的网站连接到它:

ws = new WebSocket("wss://localhost:8080/");
Run Code Online (Sandbox Code Playgroud)

这根本不起作用.就像这里写的那样,我想我必须配置SSL证书.此外,为了创建服务器,我使用了本教程,而对于Java客户端,他们实现了一个truststore.我是否必须为JavaScript做类似的事情?

riv*_*rse 8

回答可能有点迟,但经过多次尝试后我才开始工作.


首先考虑一些一般性因素:

  • 作为遵循的一般规则(对于node.js也是有效的),您必须首先使HTTPS工作以使WSS起作用.WebSocket通过HTTP工作,因此如果您的服务器已正确配置HTTPS(或HTTP),则向其添加WebSocket将使WSS(或WS)正常工作.实际上,HTTPS/WSS和HTTP/WS都可以同时工作

  • 证书非常重要,因为并非所有类型的证书都适用于Jetty(对于node.js也是如此).因此,您必须生成Jetty将接受的证书.

  • 使HTTPS工作对于自签名证书也很重要,因为您可能必须首先通过HTTPS访问服务器并在WSS可以工作之前添加异常(这可能取决于浏览器.)

  • 另一件需要考虑的事情是,上下文路径也需要正确设置.我已经通过为HTTP和WS提供单独的路径来实现它,比如/helloHTTP(S)和/wsWS(S).对于两者都可以使用相同的上下文路径来完成它,但我还没有对此进行调查


以下是我遵循的步骤.我在GitHub上放了一个工作示例.

1)使用此处的命令生成正确的自签名证书

上面的链接有一个关于如何生成正确的自签名证书的示例.(如果你有CA签名的证书,我认为程序有些不同.)

我在这里粘贴命令以方便访问.请注意,每当要求时,始终提供相同的密码(包括最后一个步骤,当您输入的密码将以明文显示在屏幕上时).

openssl genrsa -aes256 -out jetty.key
openssl req -new -x509 -key jetty.key -out jetty.crt
keytool -keystore keystore -import -alias jetty -file jetty.crt -trustcacerts
openssl req -new -key jetty.key -out jetty.csr
openssl pkcs12 -inkey jetty.key -in jetty.crt -export -out jetty.pkcs12
keytool -importkeystore -srckeystore jetty.pkcs12 -srcstoretype PKCS12 -destkeystore keystore
Run Code Online (Sandbox Code Playgroud)

2)在Jetty中拥有正确的HTTPS代码.

网上有一些资源显示如何使用Jetty进行HTTPS,但对我来说只有一个工作,它就在这里.

3)拥有处理上下文的正确代码.

这个很难 - Jetty文档页面的示例代码对我不起作用.有用的是这个.本教程还启发了我,如果我尝试使用相同的HTTP和WS路径,我可能会遇到冲突.

4)最后,为WebSocket提供正确的代码

我在这里找到了正确的WebSocket代码.拥有我们需要的是native-jetty-websocket-example.