即使我在服务器上允许使用cors,Socket.io也会出现CORS错误

时间:2016-03-01 02:36:40

标签: node.js socket.io cors

我的节点服务器和客户端在不同的端口上运行(分别为3001,5347)。 在客户端我用过,

var socket = io('http://127.0.0.1:3001');

在服务器上,我逐一尝试了以下所有内容

    1) io.set('origins', '*:*');
    2) io.set('origins', 'http://127.0.0.1:5347');
    3) io.set('origins', '*');
    4) io.set('origins', '127.0.0.1:5347');

但我收到了以下错误:

  

XMLHttpRequest无法加载http://127.0.0.1:3001/socket.io/?EIO=3&transport=polling&t=1456799439856-4590。通配符' *'不能用于“访问控制 - 允许 - 来源”#39;凭证标志为true时的标头。起源' null'因此不允许访问。

注意:我在服务器上使用express,并且我已经按照以下方式使用了cors中间件:

app.use(cors());

app和cors分别是express和cors的实例。

10 个答案:

答案 0 :(得分:21)

如果按如下方式运行Express:

var app = express();
var server = app.listen(3000);

因此,要启动socket.io,我们可以执行以下操作:

var io = require('socket.io').listen(server);

问题在于以下代码:

var http = require('http').Server(app);
var io = require('socket.io')(http);

传递给socket.io的服务器对象与我正在侦听的服务器对象不同。

答案 1 :(得分:15)

接受的答案已过时

根据官方文档,您可以将其添加到现有的http服务器中 https://socket.io/docs/server-initialization/#Attached-to-an-existing-HTTP-server

const server = require('http').createServer();
const options = { /* ... */ };
const io = require('socket.io')(server, options);
io.on('connection', socket => { /* ... */ });
server.listen(3000);

使用此选项对象启用cors似乎可以解决问题

options={
 cors:true,
 origins:["http://127.0.0.1:5347"],
}

答案 2 :(得分:2)

早在 2014 年,他们就添加了对方法的支持,作为原始参数的一部分:

let socket = io(web_server, {
    cors: { 
        origin: function(origin, fn) {
            if(origin == 'http://example.com')
                return fn(null, origin);
            return fn('Error Invalid domain');
        } 
    },
});

您可以使用外部调用、数据库或数组来验证域...

函数 fn 执行如下逻辑:

function fn(err2, origin) {
    if (err2 || !origin) {
        next(err2);
    } else {
        corsOptions.origin = origin;
        cors(corsOptions, req, res, next);
    }
}

能够动态定义 CORS 标头 https://github.com/socketio/socket.io/issues/1772

在迁移到 socket.io v3.0+ 时,关于如何设置 CORS 的迁移发生了变化。 https://socket.io/docs/v3/migrating-from-2-x-to-3-0/index.html#Configuration

socket.io v3.0 之前:

const io = require("socket.io")(httpServer, {
  origins: ["https://example.com"],

  // optional, useful for custom headers
  handlePreflightRequest: (req, res) => {
    res.writeHead(200, {
      "Access-Control-Allow-Origin": "https://example.com",
      "Access-Control-Allow-Methods": "GET,POST",
      "Access-Control-Allow-Headers": "my-custom-header",
      "Access-Control-Allow-Credentials": true
    });
    res.end();
  }
});

socket.io v3.0 之后:

const io = require("socket.io")(httpServer, {
  cors: {
    origin: "https://example.com",
    methods: ["GET", "POST"],
    allowedHeaders: ["my-custom-header"],
    credentials: true
  }
});

socket.io v3.0的origin参数支持该函数

答案 3 :(得分:1)

如果您在 Chrome、Safari 和其他浏览器上运行 socket.io 应用程序,但在 Firefox 中仍然遇到 CORS 问题,并且您使用的是自签名证书,那么问题在于 Firefox 不接受自签名证书默认情况下,您必须通过转到 Firefox 的首选项 > 证书 > 查看证书 > 添加例外来添加例外。

如果您不这样做,Firefox 会显示您发布的具有误导性的错误,但在其开发人员工具的深处,您会发现此错误:MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT。这表明 Firefox 根本不接受该证书,因为它是自签名的。

答案 4 :(得分:0)

请注意,在将应用程序传递到require('http')之前,可以将cors()与app一起使用,然后再将其传递到socket.io中。按此顺序。这也应该起作用。

const app = express();

app.use(cors());
const http = require('http').Server(app);
const io = require('socket.io')(http);

希望有帮助。

答案 5 :(得分:0)

以下代码有所帮助:

const PORT = process.env.PORT || 4000;
const app = express();
const server = app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`);
});
const io = socket(server);

答案 6 :(得分:0)

根据文档(如果您使用的是 JS,您可以忽略打字稿的内容):

const io: Server = new Server(server, {
cors: {
    origin: "*",
    methods: ["GET", "POST"]
  },
});

答案 7 :(得分:0)

这在 python-Flask-SocketIO 中对我有用

socketio =  SocketIO(app,cors_allowed_origins="*")

答案 8 :(得分:-1)

如果您使用的是Express,请在服务开始代码之前定义这样的中间件......

app.use(function(request, response, next) {
  response.header("Access-Control-Allow-Origin", "*");
  response.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

答案 9 :(得分:-1)

安装的 socket.io 版本 2 解决了我的问题。

npm install socket.io@2