我正在编写一个使用嵌入式Jetty 9.3.0.M2的安全websockets的服务器应用程序。当我在没有安全套接字的情况下运行它时,一切都是copacetic,但是当我启用安全套接字时,我的客户端拒绝连接,nmap显示端口已关闭。服务器端的日志中没有错误。
我相信我的.jks,.crt,.pem和.key文件以及我的密钥库密码都是正确的,因为同一台服务器上的其他应用程序使用相同的并正在运行。
以下是启动Jetty服务器的代码。一切都在使用常规套接字时有效。
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(表示使用安全套接字)时,日志如下所示:
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显示
PORT STATE SERVICE
8085/tcp closed unknown
我的JavaScript控制台中的错误是“连接建立错误:net :: ERR_CONNECTION_REFUSED”
当keyStorePath为null(表示使用套接字)时,日志如下所示:
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显示
PORT STATE SERVICE
8085/tcp open unknown
该应用程序在浏览器中运行良好。我很难过。我尝试了很多代码来设置SSL,但无济于事。谢谢你看这个。
已编辑,以明确我正在使用JSR-356 websockets而不是Jetty原生websockets。
已编辑将解决方案放入示例代码的注释中。
答案 0 :(得分:0)
Jetty 9.3.0仍在进行更改并且不稳定。
首先,让我们使用稳定版本的Jetty,即9.2.10.v20150310。
您的示例中的SSL,SslContextFactory和ServerConnector的设置是正确的。
示例(使用keystore
中预先创建的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
您可以使用
中的echo test客户端测试此echo类http://www.websocket.org/echo.html
只需将表单中的网址指向wss://localhost:9443/echo
并勾选TLS复选框即可。