Socket.io - 不允许访问Origin

时间:2018-04-13 13:20:17

标签: node.js express socket.io

我遇到了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配置为我的客户端域,但仍然失败。

2 个答案:

答案 0 :(得分:1)

你可以使用cors npm模块。它会解决你的问题。

 var cors = require('cors')

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

开始' *'意味着允许每个起源。您也可以输入特定来源。

答案 1 :(得分:0)

我以前见过这个问题,但从未见过它表现为交叉问题。您正在创建两个单独的http服务器。一个是制作快速服务器而另一个制作socket.io服务器。您显示的代码实际上只启动快速服务器,并且您没有显示实际启动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服务器使用与您的快速服务器相同的服务器,然后您应该能够连接正常而没有任何COR问题。

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

如果你想使用其他服务器,那么你需要与你的快速初始化代码共享它,以便它可以使用那个。