【问题标题】:Websocket dilemma between javascript and jetty embedded websocket serverjavascript和jetty嵌入式websocket服务器之间的websocket困境
【发布时间】: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 FirefoxOpera 进行通信,但连接会在几分钟后断开,有时会出现未定义的错误关闭连接。

如果 Microsoft EdgeIE 没有任何效果,当我将 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


    【解决方案1】:

    根据经验,浏览器中的 WebSocket 通过 JavaScript 无法与浏览器不知道的 wss:// 加密主机一起使用(证书未由浏览器正在使用的 CA 签名)

    自签名是不可能的,除非您也将证书链添加到浏览器中。

    这主要是因为它是一个 API,因此没有 GUI 允许您接受证书以绕过浏览器中的安全限制(对于不属于它知道的 CA 的证书)

    注意:有时(但并非总是)您可以暂时绕过此证书限制,方法是在尝试访问 wss://localhost... 之前进行正常的 https://localhost/index.html 查找,从而允许您接受该会话的证书。

    其他一些消息:

    【讨论】:

    • 但是,如果我得到一个 Well Signed 证书,那会起作用吗?
    • 浏览器将识别的 CA 签名证书将用于特定主机名,而不是用于 localhost,因此您必须牢记这一点。但在深入研究之前,请考虑使用其他一些非浏览器 websocket 客户端(命令行?)连接到您的 wss:// 服务,以确保您正确设置了服务器端。
    • 桌面应用程序在后台运行,作为windows服务,如果客户端访问需要与本地应用程序通信以完成工作的网站,客户端将与应用程序交互,因为在该站点是 websocket 客户端知道如何建立连接的地方。
    • 我有另一个提示,如果我尝试使用 http POST 方法而不是 websocket 来请求 ajax,问题还会存在吗?我可以做些什么来解决这种情况?请
    • 请发布一个新问题,不要继续这个问题。
    猜你喜欢
    • 2013-03-16
    • 2015-06-24
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 2016-04-17
    相关资源
    最近更新 更多