java使用Jetty和JavaScript客户端设置安全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();
}
}
}
密钥库文件是使用jdk/bin文件夹中的here命令创建的:
keytool.exe -keystore keystore -alias jetty -genkey -keyalg RSA
之后,我将文件移动到C目录中,以便于使用路径
通过这种配置,我的服务器似乎可以毫无问题地启动。因此,我尝试通过我的网站连接到它,如下所示:
ws = new WebSocket("wss://localhost:8080/");
这根本不起作用。与书面here一样,我认为我必须配置SSL证书。此外,为了创建服务器,我使用了这个tutorial,对于java客户端,它们实现了一个truststore
。我必须为JavaScript做类似的事情吗
# 1 楼答案
回答可能有点晚了,但经过多次尝试,我已经成功了
首先有几个一般性考虑:
作为要遵循的一般规则(对node.js也有效),您必须首先使HTTPS工作,WSS才能工作。WebSocket通过HTTP工作,因此如果您的服务器正确配置了HTTPS(或HTTP),那么向其中添加WebSocket将使WSS(或WS)工作。实际上,HTTPS/WSS和HTTP/WS可以同时工作
证书非常重要,因为并非所有类型的证书都能与Jetty一起使用(node.js也是如此)。因此,您必须生成Jetty将接受的证书
使HTTPS工作对于自签名证书也很重要,因为您可能必须首先通过HTTPS访问服务器并添加异常,然后WSS才能工作(这可能取决于浏览器)
/hello
用于HTTP(S)和/ws
用于WS(S)。这两种方法可能都使用相同的上下文路径,但我还没有对此进行调查以下是我遵循的步骤。 我在GitHub上放了一个working example
1)使用来自here的命令生成正确的自签名证书
上面的链接有一个关于如何生成正确的自签名证书的示例。(如果您有CA签名的证书,我认为过程有些不同。)
我将命令粘贴到这里以便于访问。请注意,无论何时询问,请始终提供相同的密码(包括最后一个步骤,当您键入的密码将以明文显示在屏幕上时)
2)在Jetty中具有正确的HTTPS代码
网络上有一些资源展示了如何使用Jetty实现HTTPS,但对我来说只有一个有用,那就是here
3)具有处理上下文的正确代码
这是一个很难的例子-从Jetty文档页面的代码不适合我。 起作用的是this。本教程还告诉我,如果我尝试对HTTP和WS使用相同的路径,可能会发生冲突
4)最后,为WebSocket提供正确的代码
我找到了正确的WebSocket代码here。我们所需要的是
native-jetty-websocket-example
# 2 楼答案
我想补充riverhorse的答案(我想补充一条评论,但在撰写本文时,我没有对答案发表评论所需的50个声誉)
虽然这个答案说明了如何使用自签名密钥完成此过程,但我知道了如何使用CA签名的证书
要做到这一点,我将假设你有权访问3个文件,这是你通常收到的文件 购买CA签名的证书时
第一步是将主证书和中间证书合并到一个文件中,如下所示
现在,下一步是使用示例。密钥和新的证书链。txt生成pkcs12文件(然后可以将其放入密钥库)。这些步骤与riverhorse的答案非常相似
快跑
最后一步是使用
现在,您有了jetty程序的密钥库,您可以返回riverhorse的示例,了解如何应用该密钥库
如果要检查密钥库是否具有可以运行的证书
然后使用
cat output_filename.txt
或nano output_filename.txt
查看内容这些步骤来自riverhorse的答案以及下面的2个链接
https://www.thesslstore.com/knowledgebase/ssl-install/jetty-java-http-servlet-webserver-ssl-installation/
https://wiki.eclipse.org/Jetty/Howto/Configure_SSL#Requesting_a_Trusted_Certificate
加载问题的潜在修复程序:
如果你有这个问题,一个可能的原因就是证书链。txt文件,打开它并检查两个证书之间的行是否与(5之前和之后)相同
应该如此