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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24058157/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 17:27:23  来源:igfitidea点击:

Socket.io + Node.js Cross-Origin Request Blocked

node.jssocketssocket.iocors

提问by Waleed Ahmad

I'm using node and socket.io to write a chat application. It works fine on Chrome but mozilla gives an error to enable the Cross-Origin Requests.

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

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://waleedahmad.kd.io:3000/socket.io/?EIO=2&transport=polling&t=1401964309289-2&sid=1OyDavRDf4WErI-VAAAI. This can be fixed by moving the resource to the same domain or enabling CORS.

跨域请求被阻止:同源策略不允许在http://waleedahmad.kd.io:3000/socket.io/?EIO=2&transport=polling&t=1401964309289-2&sid=1OyDavRDf4WErI-VAAAI读取远程资源。这可以通过将资源移动到同一域或启用 CORS 来解决。

Here's my code to start node server.

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

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');
});

On the client side.

在客户端。

var socket = io.connect('//waleedahmad.kd.io:3000/');

Script tag on HTML page.

HTML 页面上的脚本标记。

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

I'm also using .htaccess file in the app root directory. (waleedahmad.kd.io/node).

我也在应用根目录中使用 .htaccess 文件。(waleedahmad.kd.io/node)。

Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"

回答by Jason Sebring

Simple Server-Side Fix

简单的服务器端修复

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

or

或者

io.set('origins', '*:*');

or

或者

io.origins('*:*') // for latest version

*alone doesn't work which took me down rabbit holes.

*独自一人是行不通的,这让我陷入了兔子洞。

回答by Kwabena Berko

I am using v2.1.0and none of the above answers worked for me. This did though:

我正在使用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);

回答by Oleg

You can try to set originsoption on the server side to allow cross-origin requests:

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

io.set('origins', 'http://yourdomain.com:80');

Here http://yourdomain.com:80is the origin you want to allow requests from.

http://yourdomain.com:80是您要允许请求的来源。

You can read more about originsformat here

您可以在此处阅读有关origins格式的更多信息

回答by abe.hd

I tried above and nothing worked for me. Following code is from socket.io documentationand it worked.

我在上面尝试过,但没有任何效果对我有用。以下代码来自socket.io 文档并且它有效。

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

回答by Meloman

After read a lot of subjetcs on StakOverflow and other forums, I found the working solution for me. This solution is for working without Express.

在 StakOverflow 和其他论坛上阅读了大量 subjetcs 后,我找到了适合我的解决方案。此解决方案适用于没有 Express 的工作。

here are the prerequisites.

这是先决条件。



SERVER SIDE

服务器端

// 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

});


CLIENT SIDE

客户端

<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>

回答by Ryan Smith

This could be a certification issue with Firefox, not necessarily anything wrong with your CORS. Firefox CORS request giving 'Cross-Origin Request Blocked' despite headers

这可能是 Firefox 的认证问题,不一定是您的 CORS 有问题。尽管有标头,Firefox CORS 请求仍提供“跨源请求已阻止”

I was running into the same exact issue with Socketio and Nodejs throwing CORS error in Firefox. I had Certs for *.myNodeSite.com, but I was referencing the LAN IP address 192.168.1.10 for Nodejs. (WAN IP address might throw the same error as well.) Since the Cert didn't match the IP address reference, Firefox threw that error.

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

回答by akshay_sushir

I am facing problem while making an chat app using socket.io and node.js & React. Also this issue is not spacefic to Firefox browser, i face same issue in Edge & Chrome also.

我在使用 socket.io 和 node.js & React 制作聊天应用程序时遇到问题。此外,这个问题对于 Firefox 浏览器也不是空间问题,我在 Edge 和 Chrome 中也遇到了同样的问题。

"Cross-Origin request is blocked and it is used by some other resources..."

“跨域请求被阻止,它被其他一些资源使用......”

Then i download cors in project directory and put it in the server file index.js as below: To download simply type command using node.js :

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

npm install cors

npm 安装 cors

const cors = require('cors');
app.use(cors());

This will allow CORS to used by different resources in the files and allow cross origin request in the browser.

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

回答by Kyle Coots

Alright I had some issues getting this to work using a self signed cert for testing so I am going to copy my setup that worked for me. If your not using a self signed cert you probably wont have these issues, hopefully!

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

To start off depending on your browser Firefox or Chrome you may have different issues and I'll explain in a minute.

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

First the Setup:

首先设置:

Client

客户

// 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>

Server

服务器

var fs = require('fs');

var options = {
  key: fs.readFileSync('/path/to/your/file.pem'),
  cert: fs.readFileSync('/path/to/your/file.crt'),

};
var origins = 'https://www.YOURDOMAIN.com:*';
var app = require('https').createServer(options,function(req,res){

    // Set CORS headers
    res.setHeader('Access-Control-Allow-Origin', 'https://www.YOURDOMAIN.com:*');
    res.setHeader('Access-Control-Request-Method', '*');
    res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
    res.setHeader('Access-Control-Allow-Headers', '*');
    if ( req.method === 'OPTIONS' || req.method === 'GET' ) {
        res.writeHead(200);
        res.end();
        return;
            }

});

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

app.listen(PORT);

For development the options used on the client side are ok in production you would want the option:

对于开发,客户端使用的选项在生产中是可以的,您需要以下选项:

 rejectUnauthorized: false

You would more than likely want set to "true"

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

Next thing is if its a self signed cert you will need to vist your server in a separate page/tab and accept the cert or import it into your browser.

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

For Firefox I kept getting the error

对于 Firefox,我不断收到错误消息

MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT

The solution for me was to add the following options and accepting the cert in a different page/tab.

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

{ 
rejectUnauthorized: false
} 

In Chrome I had to open another page and accept the cert but after that everything worked fine with out having to add any options.

在 Chrome 中,我不得不打开另一个页面并接受证书,但之后一切正常,无需添加任何选项。

Hope this helps.

希望这可以帮助。

References:

参考:

https://github.com/theturtle32/WebSocket-Node/issues/259

https://github.com/theturtle32/WebSocket-Node/issues/259

https://github.com/socketio/engine.io-client#methods

https://github.com/socketio/engine.io-client#methods

回答by Aklesh Singh

If nothing works Run this in run window window+r

如果没有任何效果,请在运行窗口 window+r 中运行此命令

chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security

chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security

my problem resolved using this method, installing cors plugin works for php,node rest apis but in case of socket.io when i enable cors socket stopped working. im running both at different ports

我的问题使用这种方法解决了,安装 cors 插件适用于 php,node rest apis 但在 socket.io 的情况下,当我启用 cors 套接字停止工作时。我在不同的端口都运行

localhost:3001, and ng on localhost:4200

本地主机:3001, 和 ng 在本地主机:4200

UPDATE-- i am using npm cors package now and it work like a charm No problem with socket.io too.

更新——我现在正在使用 npm cors 包,它就像一个魅力一样工作 socket.io 也没有问题。

Add it like this

像这样添加

var express = require('express');
var app = express();
var http = require('http').Server(app);
const cors = require('cors');
var bodyParser   = require('body-parser');
app.use(cors());
app.options('*', cors());

const auth = require('./routes/auth');

 const port = 3004;
http.listen(port, () => {
  console.log( `running http at port ${port}`);
});