javascript - Firefox 中的 Websockets 不适用于多个 HTTPS 页面

标签 javascript node.js security ssl websocket

我有一个 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

最后:

内容安全策略:该页面的设置阻止了在 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 中测试)

最佳答案

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

不清楚您是如何运行这段代码的。 Chrome 似乎有可能允许扩展程序绕过该 header 限制,而 Firefox 则不允许,或者类似的东西。

关于javascript - Firefox 中的 Websockets 不适用于多个 HTTPS 页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25369125/

相关文章:

node.js - 如何为 Mongoose 中的日期字段设置正确的时区?

C# 类方法只能从某些项目调用?

javascript - 在 Vue JS 上根据父属性生成 id

javascript - Debowerify 无法与 Grunt 一起使用

c++ - Node js 原生模块,从 Objective-C block 事件监听器触发回调不起作用

.net - WCF内网安全配置

javascript - 对实际被黑网站的取证分析

javascript - 放置事件未将文件添加到事件中

javascript - 简单的 Javascript 抛出 "Uncaught SyntaxError: Unexpected token ~"

javascript - 将具有相同类的多个元素分配给具有相同类的其他元素