javascript 客户端和 netty 服务器之间的安全 websocket 连接

secure websocket connection between javascript client and netty server

我正在使用 netty 框架工作版本 4.1.6 开发 websocket 服务器。 我正在使用 netty example site 中的示例代码 这是我的服务器源代码:

public class WebSocketServer 
{
    static final int PORT = 4466;
    public static void main(String[] args) 
    {
         final SslContext sslCtx; 
         EventLoopGroup bossGroup = new NioEventLoopGroup(1);
         EventLoopGroup workerGroup = new NioEventLoopGroup();

         try {
             SelfSignedCertificate ssc = new SelfSignedCertificate();
             sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
             ServerBootstrap b = new ServerBootstrap();
             b.group(bossGroup, workerGroup)
              .channel(NioServerSocketChannel.class)
              .handler(new LoggingHandler(LogLevel.INFO))
              .childHandler(new WebSocketServerInitializer(sslCtx));

             Channel ch = b.bind(PORT).sync().channel();

             System.out.println("Open your web browser and navigate to " +
                     "http://127.0.0.1:" + PORT + '/');

             ch.closeFuture().sync();
         } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
             bossGroup.shutdownGracefully();
             workerGroup.shutdownGracefully();
         }

    }

}

WebSocketServerInitializer 源代码:

public class WebSocketServerInitializer extends ChannelInitializer<SocketChannel> 
{
    private static final String WEBSOCKET_PATH = "/websocket";
    private final SslContext sslCtx;
    public WebSocketServerInitializer(SslContext sslCtx) {
        this.sslCtx = sslCtx;
    }
    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(sslCtx.newHandler(ch.alloc()));
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new HttpObjectAggregator(65536));
        pipeline.addLast(new WebSocketServerCompressionHandler());
        pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
      //  pipeline.addLast(new WebSocketIndexPageHandler(WEBSOCKET_PATH));
        pipeline.addLast(new WebSocketFrameHandler());
    }
}

这是我的 Html 代码:

<html>
   <head>

      <script type="text/javascript">
         // Let us open a web socket
         var ws = null;
         function WebSocketTest()
         {
            if ("WebSocket" in window)
            {
               alert("WebSocket is supported by your Browser!");

               // Let us open a web socket
               ws = new WebSocket("wss://localhost:4466/websocket");
               ws.onopen = function()
               {
                  // Web Socket is connected, send data using send()
                  ws.send("Message to send");
                  alert("Message is sent...");
               };

               ws.onmessage = function (evt) 
               { 
                  var received_msg = evt.data;
                  alert(received_msg);
                  //alert("Message is received...");
               };

               ws.onclose = function()
               { 
                  // websocket is closed.
                  alert("Connection is closed..."); 
               };

               window.onbeforeunload = function(event) {
                  socket.close();
               };
            }

            else
            {
               // The browser doesn't support WebSocket
               alert("WebSocket NOT supported by your Browser!");
            }
         }
      </script>

   </head>
   <body>

      <div id="sse">
         <a href="javascript:WebSocketTest()">Run WebSocket</a>
      </div>
   </body>
</html>

我使用 Chrome 浏览器浏览页面,当我点击网页中的 link 时收到以下消息。

WebSocket connection to 'wss://localhost:4466/websocket' failed: Error in connection establishment: net::ERR_INSECURE_RESPONSE

根据这里的一些讨论,以及netty websocket示例代码,wss必须通过HTT转发PS。但是,当我在我的网页中更改以下 javascript 语句时:

ws = new WebSocket("wss://localhost:4466/websocket");

ws = new WebSocket("wss://echo.websocket.org");

它工作正常。这让我很困惑,为什么站点 echo.websocket.org 可以在没有 https 的情况下工作?为什么我的服务器不能?我的服务器源代码中是否缺少某些内容?

PS: echo.websocket.org例子在下面url:

http://jsbin.com/muqamiqimu/edit?js,console

您的浏览器无法连接到您的 websocket 服务器,因为它检测到它不安全。

发生这种情况是因为当浏览器尝试连接到您的服务器时,它会检查 SSL 证书。该证书基本上是一个证明,表明您的服务器声称是本地主机的权威服务器。

你的服务器通过它的证书声明这个,在你的情况下是自己签名的,基本上是 SelfSignedCertificate class,它声称是 "example.com".

这会产生 2 个问题:

  • 您的浏览器连接到 localhost,但不是为 localhost 获取证书,而是为 example.com
  • 获取 1
  • 您的浏览器不信任证书的签署者有权制作证书,导致其被拒绝。

有多种方法可以解决这个问题:

获取有效证书并在服务器上托管您的应用程序

这将是推荐的生产解决方案,具体取决于您在哪里获得有效证书,它可能会或可能不会花钱。

绕过证书警告

通过手动转到 http://localhost:4466/ 您可以跳过证书警告,基本上这会为证书规则添加 1 次例外,直到您重新启动浏览器

正在配置 google chrome 以接受本地主机的无效证书

虽然这可能不安全(但不像关闭所有证书验证那样不安全),但它可能是在开发机器上测试 ssl 的好方法。

您可以通过转到 chrome://flags/#allow-insecure-localhost 并打开该选项来为本地主机启用 ssl 验证。请注意,在通过调用 new SelfSignedCertificate("localhost"); 构造函数使用此选项时,您可能需要将证书的域设置为 localhost