Jetty ssl 端口未为安全 JSR-356 websockets 打开 [英] Jetty ssl port not open for secure JSR-356 websockets
问题描述
我正在编写一个使用嵌入式 Jetty 9.3.0.M2 使用安全 websockets 的服务器应用程序.当我在没有安全套接字的情况下运行它时,一切都正常,但是当我启用安全套接字时,我的客户端连接被拒绝并且 nmap 显示端口已关闭.服务器端的日志没有错误.
I'm writing a server app that uses secure websockets using embedded Jetty 9.3.0.M2. When I run it without secure sockets, everything is copacetic, but when I enable the secure sockets, my clients get connection refused and nmap shows that the port is closed. There are no errors in the log on the server side.
我相信我的 .jks、.crt、.pem 和 .key 文件以及我的密钥库密码都是正确的,因为同一台服务器上的其他应用程序正在使用相同的应用程序并且正在运行.
I believe that my .jks, .crt, .pem, and .key files and my keystore password are all correct, because other apps on this same server are using the same ones and are working.
这是启动 Jetty 服务器的代码.使用常规套接字时一切正常.
Here is the code that launches the Jetty server. Everything works when it uses the regular socket.
if (keyStorePath != null) {
// use secure sockets
server = new Server();
HttpConfiguration https = new HttpConfiguration();
https.addCustomizer(new SecureRequestCustomizer());
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(keyStorePath);
sslContextFactory.setKeyStorePassword(keyStorePassword);
sslContextFactory.setKeyManagerPassword(keyStorePassword);
ServerConnector sslConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(https));
sslConnector.setHost(serverName); // EDIT: this line was the problem, removing it fixed everything.
sslConnector.setPort(port);
server.setConnectors(new Connector[] { sslConnector });
} else {
// use regular sockets
server = new Server(port);
}
server.setStopAtShutdown(true);
server.setDumpAfterStart(false);
server.setDumpBeforeStop(false);
// Initialize JSR-356 style websocket
ServletContextHandler servletContextHandler =
new ServletContextHandler(ServletContextHandler.SESSIONS);
servletContextHandler.setContextPath(contextPath);
server.setHandler(servletContextHandler);
ServerContainer container =
WebSocketServerContainerInitializer.configureContext(servletContextHandler);
container.addEndpoint(MyWebsocketEndpoint.class);
server.start();
logger.info("Started server: " + server);
if (server.getConnectors().length > 0) {
logger.info("Connector = " + server.getConnectors()[0] +
" isRunning=" + server.getConnectors()[0].isRunning());
}
当 keyStorePath 不为 null(即使用安全套接字)时,日志如下所示:
When keyStorePath is not null (meaning use secure sockets), the log looks like this:
2015-04-23 16:07:37.634:INFO::main: Logging initialized @114ms
2015-04-23 16:07:37.863:INFO:oejs.Server:main: jetty-9.3.0.M2
2015-04-23 16:07:38.408:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@3abd7ff4{/websockets,null,AVAILABLE}
2015-04-23 16:07:38.489:INFO:oejs.ServerConnector:main: Started ServerConnector@2e4996ea{SSL,[ssl, http/1.1]}{my.server.com:8085}
2015-04-23 16:07:38.490:INFO:oejs.Server:main: Started @973ms
Apr 23, 2015 4:07:38 PM com.crowdoptic.conference.jetty.JettyWebSocketServer start
INFO: Started server: org.eclipse.jetty.server.Server@7205c140
Apr 23, 2015 4:07:38 PM com.crowdoptic.conference.jetty.JettyWebSocketServer start
INFO: Connector = ServerConnector@2e4996ea{SSL,[ssl, http/1.1]}{my.server.com:8085} isRunning=true
端口 8085 上的 nmap 显示
nmap on port 8085 shows
PORT STATE SERVICE
8085/tcp closed unknown
我的 JavaScript 控制台中的错误是连接建立错误:net::ERR_CONNECTION_REFUSED"
The error in my JavaScript console is "Error in connection establishment: net::ERR_CONNECTION_REFUSED"
当keyStorePath为null(即使用sockets)时,日志如下:
When keyStorePath is null (meaning use sockets), the log looks like this:
2015-04-23 16:15:19.624:INFO::main: Logging initialized @115ms
2015-04-23 16:15:19.847:INFO:oejs.Server:main: jetty-9.3.0.M2
2015-04-23 16:15:20.431:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@403108f6{/websockets,null,AVAILABLE}
2015-04-23 16:15:20.446:INFO:oejs.ServerConnector:main: Started ServerConnector@4efce9a2{HTTP/1.1,[http/1.1]}{0.0.0.0:8085}
2015-04-23 16:15:20.450:INFO:oejs.Server:main: Started @941ms
Apr 23, 2015 4:15:20 PM com.crowdoptic.conference.jetty.JettyWebSocketServer start
INFO: Started server: org.eclipse.jetty.server.Server@57a20888
Apr 23, 2015 4:15:20 PM com.crowdoptic.conference.jetty.JettyWebSocketServer start
INFO: Connector = ServerConnector@4efce9a2{HTTP/1.1,[http/1.1]}{0.0.0.0:8085} isRunning=true
端口 8085 上的 nmap 显示
nmap on port 8085 shows
PORT STATE SERVICE
8085/tcp open unknown
该应用在浏览器中运行良好.我难住了.我尝试了许多代码排列来设置 SSL,但无济于事.谢谢你看这个.
And the app works great from the browser. I'm stumped. I have tried many permutations of the code to set up the SSL, but to no avail. Thank you for looking at this.
编辑以明确说明我使用的是 JSR-356 websockets 而不是 Jetty 本机 websockets.
Edited to make it clear that I'm using JSR-356 websockets rather than Jetty native websockets.
编辑将解决方案放在示例代码的注释中.
Edited put solution in comments of sample code.
推荐答案
Jetty 9.3.0 仍在进行更改且不稳定.
Jetty 9.3.0 is still undergoing changes and is unstable.
首先,让我们使用稳定版的 Jetty,即 9.2.10.v20150310.
First, lets use a stable version of Jetty, namely 9.2.10.v20150310.
您在示例中对 SSL、SslContextFactory 和 ServerConnector 的设置是正确的.
Your setup of SSL, the SslContextFactory, and the ServerConnector in your example are correct.
示例(使用在 jetty-distribution/demo-base/etc
中找到的预先创建的 keystore
文件):
Example (using pre-created keystore
file found in jetty-distribution/demo-base/etc
):
package jetty.websocket;
import java.io.FileNotFoundException;
import java.net.URL;
import javax.websocket.OnMessage;
import javax.websocket.server.ServerContainer;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
public class SecureJavaxWebSocketServer
{
@ServerEndpoint(value="/echo")
public static class EchoSocket
{
@OnMessage
public String onMessage(String msg)
{
return msg;
}
}
public static void main(String[] args)
{
try
{
new SecureJavaxWebSocketServer().go();
}
catch (Throwable t)
{
t.printStackTrace(System.err);
}
}
private URL findResource(String path) throws FileNotFoundException
{
URL url = Thread.currentThread().getContextClassLoader().getResource(path);
if (url == null)
{
throw new FileNotFoundException("Resource Not Found: " + path);
}
return url;
}
public void go() throws Exception
{
Server server = new Server();
int httpsPort = 9443;
// Setup SSL
URL keystore = findResource("ssl/keystore");
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(keystore.toExternalForm());
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
sslContextFactory.addExcludeProtocols("SSLv3"); // a good thing to do
sslContextFactory.addExcludeCipherSuites(".*_GCM_.*"); // geez these ciphers are slow
// Setup HTTPS Configuration
HttpConfiguration httpsConf = new HttpConfiguration();
httpsConf.setSecurePort(httpsPort);
httpsConf.setSecureScheme("https");
httpsConf.addCustomizer(new SecureRequestCustomizer());
ServerConnector htttpsConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory,"http/1.1"),
new HttpConnectionFactory(httpsConf));
htttpsConnector.setPort(httpsPort);
server.addConnector(htttpsConnector);
// Establish base handler list
HandlerList baseHandlers = new HandlerList();
server.setHandler(baseHandlers);
// Add Servlet Context
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
baseHandlers.addHandler(context);
// Add WebSocket
ServerContainer jsrContainer = WebSocketServerContainerInitializer.configureContext(context);
jsrContainer.addEndpoint(EchoSocket.class);
// Add default handler (for errors and whatnot) - always last
baseHandlers.addHandler(new DefaultHandler());
// Lets see how the server is setup after it is started
// server.setDumpAfterStart(true);
try
{
// Start the server thread
server.start();
// Wait for the server thread to end
server.join();
}
catch (Throwable t)
{
t.printStackTrace(System.err);
}
}
}
启动控制台结果:
2015-04-23 09:53:17.279:INFO::main: Logging initialized @139ms
2015-04-23 09:53:17.346:INFO:oejs.Server:main: jetty-9.2.10.v20150310
2015-04-23 09:53:17.370:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@2437c6dc{/,null,AVAILABLE}
2015-04-23 09:53:17.574:INFO:oejs.ServerConnector:main: Started ServerConnector@71423665{SSL-http/1.1}{0.0.0.0:9443}
2015-04-23 09:53:17.575:INFO:oejs.Server:main: Started @437ms
环境测试:
$ netstat -tlnp | grep LISTEN | grep 9443
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp6 0 0 :::9443 :::* LISTEN 8918/java
$ ps auwwwx | grep 8918
joakim 8918 0.7 0.1 11822896 59728 ? Sl 09:53 0:00 /home/joakim/java/jvm/jdk-8u31-x64/bin/java -Dfile.encoding=UTF-8 -classpath /home/joakim/code/(..snip..) jetty.websocket.SecureWebSocketServer
您可以使用回声测试客户端来测试这个回声类
You can test this echo class out using the echo test client at
http://www.websocket.org/echo.html
只需将表单中的 URL 指向 wss://localhost:9443/echo
并勾选 TLS 复选框.
Just point the URL in the form to wss://localhost:9443/echo
with the TLS checkbox ticked.
这篇关于Jetty ssl 端口未为安全 JSR-356 websockets 打开的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!