Socket.io+;Node.js跨源请求被阻止

Socket.io+;Node.js跨源请求被阻止,node.js,sockets,socket.io,cors,Node.js,Sockets,Socket.io,Cors,我正在使用node和socket.io编写聊天应用程序。它在Chrome上运行良好,但mozilla在启用跨源请求时出错 已阻止跨源请求:同一源策略不允许读取位于的远程资源。这可以通过将资源移动到同一域或启用CORS来解决 这是我启动节点服务器的代码 var express = require('express'), app = express(), server = require('http').createServer(app), io = require('so

我正在使用node和socket.io编写聊天应用程序。它在Chrome上运行良好,但mozilla在启用跨源请求时出错

已阻止跨源请求:同一源策略不允许读取位于的远程资源。这可以通过将资源移动到同一域或启用CORS来解决

这是我启动节点服务器的代码

var express = require('express'),
    app = express(), 
    server = require('http').createServer(app),
    io = require('socket.io').listen(server),
    path = require('path');
server.listen(3000);

app.get('/', function(req, res) {
    res.sendfile(__dirname + '/public/index.html');
});
在客户端

var socket = io.connect('//waleedahmad.kd.io:3000/');
HTML页面上的脚本标记

<script type="text/javascript" src="//waleedahmad.kd.io:3000/socket.io/socket.io.js"></script>

您可以尝试在服务器端设置
origins
选项以允许跨源请求:

io.set('origins', 'http://yourdomain.com:80');
这里
http://yourdomain.com:80
是您希望允许来自的请求的来源


您可以阅读更多关于
源代码
格式

这可能是Firefox的认证问题,而不一定是您的CORS有任何问题

我遇到了同样的问题,Socketio和Nodejs在Firefox中抛出CORS错误。我有*.myNodeSite.com的证书,但我引用的是Nodejs的局域网IP地址192.168.1.10。(WAN IP地址也可能引发相同的错误。)由于证书与IP地址引用不匹配,Firefox引发了该错误

简单服务器端修复 注意:不要使用“socketio”软件包。。。使用“socket.io”代替。“socketio”已经过时了。有些用户似乎使用了错误的软件包

socket.io v3

const io = require('socket.io')(server, { origins: '*:*'});
文件:

cors选项:

socket.io

const io = require('socket.io')(server, { origins: '*:*'});


*
单靠它是行不通的,这让我陷入了困境。

在StakOverflow和其他论坛上读了很多主题后,我找到了适合我的有效解决方案。此解决方案适用于在没有Express的情况下使用

以下是先决条件

  • 从套接字将连接到的同一服务器调用js脚本(src=)(而不是CDN或本地调用)
  • 确保服务器端和客户端具有相同版本的socket.io
  • 所需的节点模块:,和
  • 安装让我们加密certbot和/或购买SSL证书
  • 之前在客户端声明的jQuery
  • UTF-8编码

服务器端

// DEPENDENCIES
var fs       = require('fs'),
    winston  = require('winston'),
    path     = require('path');


// LOGS
const logger = winston.createLogger({
    level     : 'info',
    format    : winston.format.json(),
    transports: [
        new winston.transports.Console({ level: 'debug' }),
        new winston.transports.File({ filename: 'err.log', level: 'err' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});


// CONSTANTS
const Port          = 9000,
      certsPath     = '/etc/letsencrypt/live/my.domain.com/';


// STARTING HTTPS SERVER 
var server = require('https').createServer({
    key:                fs.readFileSync(certsPath + 'privkey.pem'), 
    cert:               fs.readFileSync(certsPath + 'cert.pem'), 
    ca:                 fs.readFileSync(certsPath + 'chain.pem'), 
    requestCert:        false, 
    rejectUnauthorized: false 
},
(req, res) => {

    var filePath = '.' + req.url;
    logger.info('FILE ASKED : ' + filePath);

    // Default page for visitor calling directly URL
    if (filePath == './')
        filePath = './index.html';

    var extname = path.extname(filePath);
    var contentType = 'text/html';

    switch (extname) {
        case '.js':
            contentType = 'text/javascript';
            break;
        case '.css':
            contentType = 'text/css';
            break;
        case '.json':
            contentType = 'application/json';
            break;
        case '.png':
            contentType = 'image/png';
            break;      
        case '.jpg':
            contentType = 'image/jpg';
            break;
        case '.wav':
            contentType = 'audio/wav';
            break;
    }

    var headers = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
        'Access-Control-Max-Age': 2592000, // 30 days
        'Content-Type': contentType
    };

    fs.readFile(filePath, function(err, content) {
        if (err) {
            if(err.code == 'ENOENT'){
                fs.readFile('./errpages/404.html', function(err, content) {
                    res.writeHead(404, headers);
                    res.end(content, 'utf-8');
                });
            }
            else {
                fs.readFile('./errpages/500.html', function(err, content) {
                    res.writeHead(500, headers);
                    res.end(content, 'utf-8');
                });
            }
        }
        else {
            res.writeHead(200, headers);
            res.end(content, 'utf-8');
        }
    });

    if (req.method === 'OPTIONS') {
        res.writeHead(204, headers);
        res.end();
    }

}).listen(port); 


//OPENING SOCKET
var io = require('socket.io')(server).on('connection', function(s) {

    logger.info("SERVER > Socket opened from client");

    //... your code here

});
<script src="https://my.domain.com:port/js/socket.io.js"></script>
<script>
    $(document).ready(function() {

        $.socket = io.connect('https://my.domain.com:port', {
            secure: true // for SSL
        });

        //... your code here

    });
</script>

客户端

// DEPENDENCIES
var fs       = require('fs'),
    winston  = require('winston'),
    path     = require('path');


// LOGS
const logger = winston.createLogger({
    level     : 'info',
    format    : winston.format.json(),
    transports: [
        new winston.transports.Console({ level: 'debug' }),
        new winston.transports.File({ filename: 'err.log', level: 'err' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});


// CONSTANTS
const Port          = 9000,
      certsPath     = '/etc/letsencrypt/live/my.domain.com/';


// STARTING HTTPS SERVER 
var server = require('https').createServer({
    key:                fs.readFileSync(certsPath + 'privkey.pem'), 
    cert:               fs.readFileSync(certsPath + 'cert.pem'), 
    ca:                 fs.readFileSync(certsPath + 'chain.pem'), 
    requestCert:        false, 
    rejectUnauthorized: false 
},
(req, res) => {

    var filePath = '.' + req.url;
    logger.info('FILE ASKED : ' + filePath);

    // Default page for visitor calling directly URL
    if (filePath == './')
        filePath = './index.html';

    var extname = path.extname(filePath);
    var contentType = 'text/html';

    switch (extname) {
        case '.js':
            contentType = 'text/javascript';
            break;
        case '.css':
            contentType = 'text/css';
            break;
        case '.json':
            contentType = 'application/json';
            break;
        case '.png':
            contentType = 'image/png';
            break;      
        case '.jpg':
            contentType = 'image/jpg';
            break;
        case '.wav':
            contentType = 'audio/wav';
            break;
    }

    var headers = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
        'Access-Control-Max-Age': 2592000, // 30 days
        'Content-Type': contentType
    };

    fs.readFile(filePath, function(err, content) {
        if (err) {
            if(err.code == 'ENOENT'){
                fs.readFile('./errpages/404.html', function(err, content) {
                    res.writeHead(404, headers);
                    res.end(content, 'utf-8');
                });
            }
            else {
                fs.readFile('./errpages/500.html', function(err, content) {
                    res.writeHead(500, headers);
                    res.end(content, 'utf-8');
                });
            }
        }
        else {
            res.writeHead(200, headers);
            res.end(content, 'utf-8');
        }
    });

    if (req.method === 'OPTIONS') {
        res.writeHead(204, headers);
        res.end();
    }

}).listen(port); 


//OPENING SOCKET
var io = require('socket.io')(server).on('connection', function(s) {

    logger.info("SERVER > Socket opened from client");

    //... your code here

});
<script src="https://my.domain.com:port/js/socket.io.js"></script>
<script>
    $(document).ready(function() {

        $.socket = io.connect('https://my.domain.com:port', {
            secure: true // for SSL
        });

        //... your code here

    });
</script>

$(文档).ready(函数(){
$.socket=io.connect('https://my.domain.com:port', {
secure:true//for SSL
});
//…您的代码在这里
});

我尝试了上述方法,但没有任何效果。下面的代码来自,它工作正常

io.origins((origin, callback) => {
  if (origin !== 'https://foo.example.com') {
      return callback('origin not allowed', false);
  }
  callback(null, true);
});

好吧,我在使用自签名证书进行测试时遇到了一些问题,所以我要复制我的设置,它对我有效。如果您不使用自签名证书,您可能不会有这些问题,希望如此

首先,根据您的浏览器Firefox或Chrome,您可能会遇到不同的问题,我会在一分钟内解释

首先,设置:

客户端

// May need to load the client script from a Absolute Path
<script src="https://www.YOURDOMAIN.com/node/node_modules/socket.io-client/dist/socket.io.js"></script>
<script>
var options = {
          rememberUpgrade:true,
          transports: ['websocket'],
          secure:true, 
          rejectUnauthorized: false
              }
var socket = io.connect('https://www.YOURDOMAIN.com:PORT', options);

// Rest of your code here
</script>
对于开发,客户端使用的选项在生产中是可以使用的。您可能需要以下选项:

 rejectUnauthorized: false
您很可能希望设置为“true”

接下来,如果是自签名证书,您需要在单独的页面/选项卡中访问服务器,并接受证书或将其导入浏览器

对于Firefox,我不断地得到错误

MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT
我的解决方案是添加以下选项并在不同的页面/选项卡中接受证书

{ 
rejectUnauthorized: false
} 
在Chrome中,我不得不打开另一个页面并接受证书,但在那之后,一切都很好,不需要添加任何选项

希望这有帮助

参考资料:


我使用的是
v2.1.0
,上面的答案对我都不起作用。 但这确实:

import express from "express";
import http from "http";

const app = express();
const server = http.createServer(app);

const sio = require("socket.io")(server, {
    handlePreflightRequest: (req, res) => {
        const headers = {
            "Access-Control-Allow-Headers": "Content-Type, Authorization",
            "Access-Control-Allow-Origin": req.headers.origin, //or the specific origin you want to give access to,
            "Access-Control-Allow-Credentials": true
        };
        res.writeHead(200, headers);
        res.end();
    }
});

sio.on("connection", () => {
    console.log("Connected!");
});

server.listen(3000);

我在使用socket.io和node.js制作聊天应用程序时遇到了问题&React。另外,这个问题对于Firefox浏览器来说并不重要,我在Edge和Chrome浏览器中也面临同样的问题

“跨源请求被阻止,并被其他一些资源使用…”

然后我在项目目录中下载cors,并将其放入服务器文件index.js中,如下所示:要下载,只需使用node.js键入command:

npm安装cors


这将允许文件中的不同资源使用CORS,并允许浏览器中的跨源请求。

我也遇到过同样的问题,任何解决方案都能为我解决

原因是我正在使用allowRequest接受或拒绝连接,使用我在查询参数中传递的令牌

我在客户端的查询参数名称中有一个输入错误,所以连接总是被拒绝,但浏览器抱怨cors

一旦我修正了输入错误,它就开始按预期工作,我不需要使用任何额外的东西,global express cors设置就足够了


因此,如果有任何东西适合您,并且您正在使用allowRequest,请检查此函数是否正常工作,因为它抛出的错误在浏览器中显示为cors错误。除非您在想要拒绝连接时手动在那里添加cors头,否则我猜。

如果您正在获取
io.set not a function
io.origins not a function
,您可以尝试这样的表示法:

import express from 'express';
import { Server } from 'socket.io';
const app = express();
const server = app.listen(3000);
const io = new Server(server, { cors: { origin: '*' } });

对于任何在这里寻找新的Socket.io(3.x)的人来说,这是非常有用的

特别是这个片段:

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

//UPDATE: this is seems to be deprecated
//let io = require('socket.io').listen(app.listen(9009));
//New Syntax:
const io = require('socket.io')(app.listen(9009));

app.all('/', function (request, response, next) {
    response.header("Access-Control-Allow-Origin", "*");
    response.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
});
<!--LOAD THIS SCRIPT FROM SOMEWHERE-->
<script src="http://127.0.0.1:9009/socket.io/socket.io.js"></script>
<script>
    var socket = io("127.0.0.1:9009/", {
        "force new connection": true,
        "reconnectionAttempts": "Infinity", 
        "timeout": 10001, 
        "transports": ["websocket"]
        }
    );
</script>

我只是想说,在尝试了很多东西之后,解决CORS问题的方法就是使用旧版本的socket.io(版本2.2.0)。我的package.json文件现在如下所示:

{
  "name": "current-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "devStart": "nodemon server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "socket.io": "^2.2.0"
  },
  "devDependencies": {
    "nodemon": "^1.19.0"
  }
}



如果使用此命令执行
npm install
,您可能会发现在尝试使用socket.io时CORS问题消失了。至少它对我起了作用。

对socket.io和socket.io-client使用相同的版本修复了我的问题。

看看这个:

服务器:

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

//UPDATE: this is seems to be deprecated
//let io = require('socket.io').listen(app.listen(9009));
//New Syntax:
const io = require('socket.io')(app.listen(9009));

app.all('/', function (request, response, next) {
    response.header("Access-Control-Allow-Origin", "*");
    response.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
});
<!--LOAD THIS SCRIPT FROM SOMEWHERE-->
<script src="http://127.0.0.1:9009/socket.io/socket.io.js"></script>
<script>
    var socket = io("127.0.0.1:9009/", {
        "force new connection": true,
        "reconnectionAttempts": "Infinity", 
        "timeout": 10001, 
        "transports": ["websocket"]
        }
    );
</script>
客户端:

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

//UPDATE: this is seems to be deprecated
//let io = require('socket.io').listen(app.listen(9009));
//New Syntax:
const io = require('socket.io')(app.listen(9009));

app.all('/', function (request, response, next) {
    response.header("Access-Control-Allow-Origin", "*");
    response.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
});
<!--LOAD THIS SCRIPT FROM SOMEWHERE-->
<script src="http://127.0.0.1:9009/socket.io/socket.io.js"></script>
<script>
    var socket = io("127.0.0.1:9009/", {
        "force new connection": true,
        "reconnectionAttempts": "Infinity", 
        "timeout": 10001, 
        "transports": ["websocket"]
        }
    );
</script>

var socket=io(“127.0.0.1:9009/”{
“强制新连接”:正确,
“重新连接尝试”:“无限”,
“超时”:10001,