我试图通过Apache代理使用socket.io服务但是我一直收到这个错误:
当请求的凭据模式为“include”时,响应中的“Access-Control-Allow-Origin”标头的值不能是通配符“*”。因此,不允许原点“http://localhost:18996”访问。 XMLHttpRequest发起的请求的凭证模式由withCredentials属性控制。
这是我的apache配置
<VirtualHost *:443>
ServerName myserver.com
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, cl$
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
DocumentRoot /var/www/api
SSLEngine on
SSLCertificateFile /etc/ssl/MYSSL
SSLCertificateKeyFile /etc/ssl/MYSSL
ProxyRequests Off
ProxyPreserveHost On
ProxyVia Full
<Proxy *>
Require all granted
</Proxy>
<Location /api1>
ProxyPass http://127.0.0.1:8005
ProxyPassReverse http://127.0.0.1:8005
</Location>
<Location /api2>
ProxyPass http://127.0.0.1:9000
ProxyPassReverse http://127.0.0.1:9000
</Location>
<Location /socketioservice>
ProxyPass http://127.0.0.1:9090
ProxyPassReverse http://127.0.0.1:9090
</Location>
</VirtualHost>
这是我的Node JS代码:
const express = require('express'),
app = express(),
bodyParser = require('body-parser'),
server = require('http').createServer(app),
io = require('socket.io')(server);
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
io.on('connection', user => {
//Socket.io Functions
});
server.listen(8000, () => console.log('Server Running'));
我有其他NodeJS服务在你看到的同一个盒子上运行,那些只是Express JS Apis,它们工作正常(使用你在socket.io代码中看到的相同的cors配置)。
我试图像这样改变角色设置:
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors({ origin: '*' }));
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', false);
next();
});
const server = app.listen(cross.NormalizePort(process.env.PORT || 9090));
const io = require('socket.io').listen(server, {
log: false,
agent: false,
origins: '*:*',
transports: ['websocket', 'htmlfile', 'xhr-polling', 'jsonp-polling', 'polling']
});
但这给了我完全相同的结果。我试图在没有cors的情况下完全使用它,我也得到同样的错误。
我在AngularJS应用程序中使用它,工厂如此:
.factory('Links', ['$rootScope', function ($rootScope) {
let socket = io.connect('https://myurl/socketioservice', { secure: true });
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$apply(function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
$rootScope.$apply(function () {
if (callback) {
callback.apply(socket, args);
}
});
});
}
};
}])
我已经验证了socket.io服务通过在本地运行它可以正常工作我可以使用http://localhost:8000
连接到它。当我将它部署到生产框时,我可以像这样使用它:http://prodipaddress:8000
并且也可以使用它。
但是,我需要能够运行Apache代理,否则由于防火墙规则,无法从网络外部访问它。
如何配置cors以允许我连接到我的socket.io服务?
答案 0 :(得分:1)
您正在使用凭据模式(意味着您要从角应用程序发送一些身份验证cookie),而对于CORS规范,您无法在此模式下使用通配符*。
您应该更改Access-Control-Allow-Origin标头以匹配生成请求的特定主机
你可以改变这一行:
res.header('Access-Control-Allow-Origin', '*');
到
res.header('Access-Control-Allow-Origin', 'http://localhost:18996');
但要更通用:
res.setHeader('Access-Control-Allow-Origin', req.header('origin')
|| req.header('x-forwarded-host') || req.header('referer') || req.header('host'));