【问题标题】:Socket.io - Origin is not allowed accessSocket.io - Origin 不允许访问
【发布时间】:2018-09-23 21:00:32
【问题描述】:

我在使用 socket.io 时遇到了这个奇怪的问题。我有一个在端口 5000 上运行的快速应用程序。我已经像这样配置了 socket.io:

const app = require('../index');
const http = require('http');
const server = http.Server(app);
const io = require('socket.io')(server);

io.on('connection', function (socket) {
    console.log('User has connected');
    socket.emit('connect', {
        message: 'Hello World'
    });
});

然后我将这段代码导入到我的 index.js 文件中,如下所示:

const express = require('express');
const app = module.exports = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const request = require('request');
const boxRoutes = require('./routes/v1/boxRoutes');
const bidRoutes = require('./routes/v1/bidRoutes');
// use body parser so we can get info from POST and/or URL parameters
app.use(bodyParser.urlencoded({ limit: '10mb', extended: true }));
app.use(bodyParser.json({ limit: '10mb' }));

require('./services/usersClass');

// cors set up
app.use(cors());
app.use(function (req, res, next) {
  console.log('Headers Middleware Called');

  // Website you wish to allow to connect
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');

  // Request methods you wish to allow
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');

  // Request headers you wish to allow
  res.setHeader('Access-Control-Allow-Headers', 'origin, x-requested-with, content-type, accept, x-xsrf-token', 'token');

  // Set to true if you need the website to include cookies in the requests sent
  // to the API (e.g. in case you use sessions)
  res.setHeader('Access-Control-Allow-Credentials', true);

  // Request headers you wish to expose
  res.setHeader('Access-Control-Expose-Headers', false);

  next();
});

// Middleware to authenticate the requests to this service
app.use(function(req, res, next) {
    console.log('Auth Middleware Called');
    if(!req || !req.headers['authorization']) return res.sendStatus(401);
    const token = req.headers['authorization'].split(' ')[1];
    request.post(
        'http://localhost:4000/api/v1/users/auth',
        { 
            headers: {
                'Authorization': `Bearer ${token}`
            }
        },
        function (error, response, body) {
            if (!error && response.statusCode == 200) {
                const data = JSON.parse(body);
                res.locals.user = data.user;
                next();
            } else {
                console.log('Request has failed. Please make sure you are logged in');
                res.sendStatus(401);
            }
        }
    );
});

app.use('/api/v1/boxes/', boxRoutes);
app.use('/api/v1/bids/', bidRoutes);

// disable 'powered by'
app.disable('x-powered-by');

app.listen(5000, () => {
    console.log('Trading service is running on port 5000');
});

现在,在我的客户端代码中,我尝试在用户登录时建立 socket.io 连接。每次尝试连接到服务器时,都会出现以下错误:

加载失败 http://localhost:5000/socket.io/?EIO=3&transport=polling&t=MA_9wXE: 对预检请求的响应未通过访问控制检查: 响应中“Access-Control-Allow-Origin”标头的值必须 当请求的凭据模式为时,不是通配符“*” '包括'。因此不允许使用原点“http://localhost:3000” 使用权。发起请求的凭证模式 XMLHttpRequest 由 withCredentials 属性控制。

我不明白为什么连接失败。我已将Access-Control-Allow-Origin 配置到我的客户端域,但仍然失败。

【问题讨论】:

  • 您的 CORs 错误消息还显示您的网页来自端口 3000,但您显示的快速服务器位于端口 5000。所以,这非常令人困惑。这张图片中是否还有另一个 Web 服务器在端口 3000 上运行?

标签: node.js express socket.io


【解决方案1】:

您可以使用 cors npm 模块。它将解决您的问题。

 var cors = require('cors')

 var app = express()
 app.use(cors({origin: '*'}))

start '*' 表示允许每个来源。您也可以输入特定来源。

【讨论】:

    【解决方案2】:

    我以前见过这个问题,但从未见过它表现为跨源问题。您正在创建两个单独的 http 服务器。一个你正在制作你的 express 服务器,另一个你正在制作你的 socket.io 服务器。您显示的代码仅实际启动 express 服务器,而您没有显示实际启动 socket.io 服务器的代码。

    您可以在此处创建这两个单独的服务器:

    const server = http.Server(app);     // creates the http server you use for socket.io
    
    app.listen(5000, () => {...});       // creates the http server you use with Express
    

    app.listen() 内部,它创建自己的新服务器并启动它。您的其他服务器从未启动(至少根据您在此处显示的代码)。

    您可能想要做的是让您的 socket.io 服务器使用与您的 express 服务器相同的服务器,然后您应该能够正常连接而不会出现任何 CORs 问题。

    如果你想使用app.listen(),它将返回它创建的server对象,你需要使用它来初始化socket.io。

    如果您想使用另一台服务器,则需要将其与您的快速初始化代码共享,以便它可以使用该服务器。

    【讨论】:

    • 好的,我尝试了您的建议,但现在我收到一个不同的错误消息:“预检响应具有无效的 HTTP 状态代码 400。”
    • @DavidLasry - 能否请您向我们展示您的进行 ajax 调用的客户端代码。我仍然不明白为什么你甚至首先有一个 CORS 请求。但是,那个 CORS 错误是因为您的服务器没有处理 OPTIONS 请求。看来您可能在触发 COR 的 ajax 调用上执行自定义标头之类的操作。
    • @DavidLasry - 您的问题中似乎没有任何客户端代码。而且,也没有任何编辑,所以显然你的编辑没有工作。
    猜你喜欢
    • 2012-08-10
    • 2013-01-20
    • 2017-03-19
    • 1970-01-01
    • 2019-12-20
    • 2017-08-08
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多