繁体   English   中英

无法与 javascript 建立连接到安全的 websocket 服务器

[英]Can't establish a connection with javascript to a secure websocket server

我的开发环境是这样的:

  • 操作系统:微软 Windows 10
  • PHP 框架:Laravel 8.0
  • PHP 版本 7.4
  • Websocket 服务器:cboden/ratchet 0.4.3
  • WAMP 服务器 3.2.0 (Apache 2.4.41)
  • Firefox 91.0.1(64 位)/铬

我创建了一个新的 Laravel 应用程序来实现一个安全的 Websocket 服务器,并在客户端(Laravel 刀片文件)使用普通的 javascript 连接到它。 据我所见,websocket 服务器运行良好,但 web 浏览器无法连接,如下图所示:

在此处输入图像描述

我试过使用不同的 URL,有和没有端口号,但无济于事。 我使用openssl.exe工具创建了一个SSL证书和私钥文件,并将它们放在命令文件夹中以供测试。

这是我的安全 Websocket 服务器的句柄代码:

   public function handle()
   {
      $loop   = Factory::create();
      $webSock = new SecureServer(
         new Server('0.0.0.0:8090', $loop),
         $loop,
         array(
            'local_cert'        => 'certificate.crt', 
            'local_pk'          => 'private.key', 
            'allow_self_signed' => TRUE, 
            'verify_peer' => FALSE
         )
      );

      // Ratchet magic
      $webServer = new IoServer(
         new HttpServer(
            new WsServer(
               new WebSocketController()
            )
         ),
         $webSock
      );

      $loop->run();
   }

我在httpd-ssl.conf文件中的虚拟主机:

<VirtualHost *:443>
  ServerName ssa
  DocumentRoot "d:/web/app/ssa/public"
  SSLEngine on
  
  SSLCertificateFile "${SRVROOT}/conf/certificate.crt"
  SSLCertificateKeyFile "${SRVROOT}/conf/private.key"

  SSLVerifyClient none
  SSLVerifyDepth 10

  <Directory "d:/web/app/ssa/public">
    Options +Indexes +Includes +FollowSymLinks +MultiViews
    AllowOverride All
    Require local
  </Directory>
  
  ProxyRequests Off 
  ProxyPass /wss/  ws://ssa:8090
</VirtualHost>

加载了 Apache 模块 proxy_module、proxy_http_module 和 proxy_wstunnel_module。 web 应用程序在 HTTPS 中运行。之前,它在 HTTP 和 WS 上运行并且一切正常,但我需要保护此应用程序并且我在连接到安全的 websocket 服务器时遇到问题。

我错过了什么吗?

我的Websocket服务器或者Apache配置有问题吗?

您肯定是在尝试连接到错误的目的地。 它说 wss:///ssa/wss/,但它可能应该是 wss://your.site.domain/ssa/wss/。

因此,让我们看一下前端代码并找出它的问题所在。

好的,正如@apokryfos 指出的那样,我试图通过 HTTPS 代理 websocket 服务器,但我做错了。

我将我的 websocket 服务器更改为非安全服务器,并对我的虚拟主机进行了以下更改:

<VirtualHost *:443>
  ServerName ssa
  DocumentRoot "d:/web/app/ssa/public"
  SSLEngine on
  
  SSLCertificateFile "${SRVROOT}/conf/certificate.crt"
  SSLCertificateKeyFile "${SRVROOT}/conf/private.key"

  SSLVerifyClient none
  SSLVerifyDepth 10

  <Directory "d:/web/app/ssa/public">
    Options +Indexes +Includes +FollowSymLinks +MultiViews
    AllowOverride All
    Require local
  </Directory>
  
  Redirect /wss /wss/
  ProxyPass /wss/ ws://127.0.0.1:8090/
  ProxyPassReverse /ws/ wss://127.0.0.1:8090/
</VirtualHost>

在客户端,浏览器现在可以通过 HTTPS 端口联系后端 WS 服务器:

// The connection to the WebSocket Server.
var socket = new WebSocket("wss://ssa:443/wss/");

我从Apache Config: Websockets Proxy WSS request to WS backend得到这个解决方案

现在我得到了我的非安全 Websocket 服务器通过 HTTPS 发送/接收。当然,这不是我期望应用于我的需求的解决方案,但它确实有效。 我仍然希望找到一个正式的解决方案,在不使用代理机制的情况下将普通 JavaScript 客户端连接到安全的 Websocket 服务器 (wss://)。

为了不让更多信息使我的第一个答案复杂化,我在这里提供了毕竟对我真正有用的答案。

我创建了安全 Websocket 服务器,如下所示:

public function handle() {
      $loop = Factory::create();
      $webSock = new SecureServer(
         new Server('0.0.0.0:8443', $loop),
         $loop,
         array(
            'local_cert' => 'C:/wamp64/bin/apache/apache2.4.41/conf/server.crt',
            'local_pk' => 'C:/wamp64/bin/apache/apache2.4.41/conf/server.key', 
            'allow_self_signed' => TRUE, 
            'verify_peer' => FALSE
         )
      );
      $webServer = new IoServer(
         new HttpServer(
            new WsServer(
               new WebSocketController()
            )
         ),
         $webSock
      );
      $loop->run();
}

注意我把端口号改成了8443(我不认为这有什么关系)并且还更改了新的证书和密钥文件,生成如下:

openssl req -config config.conf -new -x509 -out server.crt -days 3650

config.conf 文件是:

[req]
default_bits = 2048
encrypt_key = no
default_md = sha256
default_keyfile = server.key
distinguished_name = req_distinguished_name
prompt = no

[req_distinguished_name]
C = KH
ST = Siem Reap
L = SR
O = AHC
OU = IT
CN = localhost

[bs_section]
CA=false

所有不同之处在于最后一行CA=false表示我没有签署或充当证书颁发机构 (CA)。 这摆脱了MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY消息。

然后,我去掉了在我的 httpd-ssl.conf 文件中定义代理的行:

<VirtualHost *:443>
  ServerName ssa
  DocumentRoot "d:/web/app/ssa/public"
  SSLEngine on
  
  SSLCertificateFile "${SRVROOT}/conf/server.crt"
  SSLCertificateKeyFile "${SRVROOT}/conf/server.key"

  SSLVerifyClient none
  SSLVerifyDepth 10

  <Directory "d:/web/app/ssa/public">
    Options +Indexes +Includes +FollowSymLinks +MultiViews
    AllowOverride All
    Require local
  </Directory>
  
  #Redirect /wss /wss/
  #ProxyPass /wss/ ws://127.0.0.1:8090/
  #ProxyPassReverse /ws/ wss://127.0.0.1:8090/
</VirtualHost>

请注意,对于这个虚拟主机,我使用了与安全 Websocket 服务器相同的证书和密钥文件。

好的,这就是我的证书问题。

现在一切都按预期工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM