Firefox 中的 Websocket 无法处理多个 HTTPS 页面

Posted

技术标签:

【中文标题】Firefox 中的 Websocket 无法处理多个 HTTPS 页面【英文标题】:Websockets in Firefox not working with several HTTPS pages 【发布时间】:2014-08-18 17:46:11 【问题描述】:

我有一个 websocket 客户端-服务器应用程序。这是客户的简化代码:

const HOST = "wss://localhost:8000";

const SUB_PROTOCOL= "sub-protocol"; 

var websocket = new WebSocket(HOST, SUB_PROTOCOL);

websocket.onopen  = function(evt)    ... ;
websocket.onclose = function(evt)    ... ;
websocket.onerror = function(evt)    ... ;
websocket.onmessage = function(evt)  ... ;

这里是服务器:

const PORT = 8000;
const SUBPROTOCOL = 'sub-protocol';

var WebSocketServer = require('websocket').server;

var https = require('https');
var fs = require('fs');

// Private key and certification (self-signed for now) 
var options = 
  key: fs.readFileSync('cert/server.key'),
  cert: fs.readFileSync('cert/server.crt')
;

var server = https.createServer(options, function(request, response) 
    console.log((new Date()) + ' Received HTTP(S) request for ' + request.url);
    response.writeHead(404);
    response.end();
); 

// bind server object to listen to PORT number
server.listen(PORT, function() 
    console.log((new Date()) + ' Server is listening on port ' + PORT);
);

wsServer = new WebSocketServer(
    httpServer: server,
    // You should not use autoAcceptConnections for production
    // applications, as it defeats all standard cross-origin protection
    // facilities built into the protocol and the browser.  You should
    // *always* verify the connection's origin and decide whether or not
    // to accept it.
    autoAcceptConnections: false
);


function originIsAllowed(origin) 
  // put logic here to detect whether the specified origin is allowed.
  return true;


// If autoAcceptConnections is set to false, a request event will be emitted
// by the server whenever a new WebSocket request is made
wsServer.on('request', function(request) 

    if (!originIsAllowed(request.origin)) 
      // Make sure we only accept requests from an allowed origin
      request.reject();
      console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
      return;
    

    // accepts connection and return socket for this connection
    var connection = request.accept(SUB_PROTOCOL, request.origin);

    console.log((new Date()) + ' Connection accepted.');

    // when message is received
    connection.on('message', function(message) 

        // echo
        connection.send(connection, message.utf8Data);

    );


    connection.on('close', function(reasonCode, description) 
        console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
    );

);

即使使用一些 HTTPS 页面(在 Twitter、mail.ru 上测试),客户端和服务器都可以正常工作。但由于某些原因,例如 Facebook 或 GitHub 上没有。

javascript 控制台中我得到这个:

Exception message: "", result: 2153644038, name: "", filename: "", lineNumber: 0, columnNumber: 0, inner: null, data: null

然后是巨大的堆栈跟踪:粘贴它here

最后:

Content Security Policy: The page's settings blocked the loading of a resource at wss://localhost:8000/ ("connect-src https://github.com:443 https://ghconduit.com:25035 https://live.github.com:443 https://uploads.github.com:443 https://s3.amazonaws.com:443").

我看不出这些页面与有效的页面有何不同。我还想指出,这些页面可以在 Chrome 中使用。

(在 Firefox 31 中测试)

【问题讨论】:

【参考方案1】:

WebSocket 连接失败的页面有一个 Content-Security-Policy 标头,其中 connect-src 指令设置为仅允许连接到一组列入白名单的域。这意味着从该页面到任何未列入白名单的域的所有连接都将失败。

不清楚您是如何运行此代码的。 Chrome 似乎有可能允许扩展绕过该标头限制,而 Firefox 不允许,或类似的东西。

【讨论】:

是的,客户端的代码是作为内容脚本在 firefox/chrome 插件中运行的库的一部分。所以我想这与此无关?如果我可以破坏内容安全策略,就没有理由拥有它,对吧。还好,这只是一种实验方法,所以如果它死了,我可以关闭它,以免为时已晚。 @dakov 我找不到让 Firefox 在 Content-Security-Policy 标头和插件方面表现得像 Chrome 的方法。看起来像一个死胡同。

以上是关于Firefox 中的 Websocket 无法处理多个 HTTPS 页面的主要内容,如果未能解决你的问题,请参考以下文章

firefox使用 websocket 报无法建立到 ws://服务器的连接错误,ie和chrom都可以,求解释。。

Firefox Websocket 安全问题

Websocket 连接不会在 FireFox 中关闭

Ubuntu 13.10 中的 websocket 连接失败

angular2项目在firefox上加载时websocket中断

Watson语音到文本 - 无法构造'WebSocket':URL包含片段标识符