【发布时间】:2017-01-01 02:50:00
【问题描述】:
我有一个 javascript API,它包含在某些网站中。由于某些原因,需要将浏览器端与用 Java 编写的桌面应用程序进行通信。如您所见,所有内容都是主机本地的。
我的第一个解决方案是为每个已知浏览器使用插件/扩展,但缺乏良好的支持和大量的依赖项阻止了我选择该选项。然后我的第二种方法是在双方都使用websockets,服务器在Java应用程序中,客户端是浏览器,一切都会很完美,但是一个大问题浮出水面: HTTPS 网站无法与不安全的 websocket 服务器建立连接,与 Java 无关,也与服务器是否在 localhost 上无关。
我一直在使用的 java_websocket API 不足以解决这个问题,而在 google 中 Jetty 是一个适合我的好名字。我在几个小时内就开始使用 Jetty,在一些示例之后,我得到了两个类,一个服务器端点 (EchoSocket) 和服务器 (EventServer):
EventServer.java
import java.util.logging.Level;
import java.util.logging.Logger;
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.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
public class EventServer {
public static void main(String[] args) {
try {
Server server = new Server();
int httpsPort = 8771;
SslContextFactory scf = new SslContextFactory("mykeystore.jks");
scf.setKeyStorePassword("blaStore");
scf.setKeyManagerPassword("blablaKey");
SslConnectionFactory sslConnectionFactory = new SslConnectionFactory(scf, "http/1.1");
HttpConfiguration https = new HttpConfiguration();
https.setSecurePort(httpsPort);
https.setSecureScheme("https");
https.addCustomizer(new SecureRequestCustomizer());
ServerConnector sslConnector = new ServerConnector(server,
sslConnectionFactory,
new HttpConnectionFactory(https)
);
sslConnector.setPort(httpsPort);
server.addConnector(sslConnector);
HandlerList baseHandler = new HandlerList();
server.setHandler(baseHandler);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); //ServletContextHandler.SESSIONS
context.setContextPath("/");
baseHandler.addHandler(context);
ServerContainer jsrContainer = WebSocketServerContainerInitializer.configureContext(context);
jsrContainer.addEndpoint(EchoSocket.class);
baseHandler.addHandler(new DefaultHandler());
server.start();
server.dump(System.err);
server.join();
} catch (Throwable ex) {
ex.printStackTrace(System.err);
}
}
}
EchoSocket.java
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value="/echo")
public class EchoSocket
{
@OnMessage
public void onMessage(javax.websocket.Session session, String message){
session.getAsyncRemote().sendText("welcomeeee");
}
@OnError
public void onError(Throwable cause)
{
cause.printStackTrace(System.err);
}
}
使用Websocket online test 我可以从 Mozilla Firefox 和 Opera 进行通信,但连接会在几分钟后断开,有时会出现未定义的错误关闭连接。
如果 Microsoft Edge 和 IE 没有任何效果,当我将 URI 写为 wss://localhost:8771/echo 时错误是:
SCRIPT12017: WebSocket Error: SECURITY_ERR, Cross zone connection not allowed
当我尝试使用 wss://127.0.0.1:8771/echo 时,错误是:
SCRIPT12038: WebSocket Error: Network Error 12038, The host name in the certificate is invalid or does not match
在 Google Chrome 中,URI 的两种方式似乎都不起作用,没有连接,错误是:
WebSocket connection to 'wss://127.0.0.1:8771/echo' failed: Error in connection establishment: net::ERR_NETWORK_CHANGED
在另一种情况下:
WebSocket connection to 'wss://localhost:8771/echo' failed: Error in connection establishment: net::ERR_CONNECTION_CLOSED
所以,我需要一些帮助,但也许你可以回答我接下来的一些问题:
- 我的 Jetty 示例是否正确?如果不正确,我该如何纠正?
- 我应该尝试其他库还是旧版本的 Jetty 以使其在大多数浏览器中都能正常工作?
- 我应该看到其他语言(如 C#)的 websocket 服务器的其他实现吗?
- 我必须在我的 SSL 证书中设置什么主机名或 SubjectAltName 才能允许来自 IE 和 Edge 的连接?可能是“本地主机”或“127.0.0.1”。
请提前谢谢,对不起,我的英语。
【问题讨论】:
标签: javascript java websocket jetty java-websocket