[英]SignalR 2.0 CORS Chrome Disable Web Security Strange Behavior
我正在努力使CORS与SignalR 2.0.0一起使用-我知道有很多关于它的SO帖子,并且我一直在仔细研究它们。
在Chrome中禁用了网络安全性的情况下进行测试时遇到了一个问题,希望有人可以解释。
我在IIS Express(不同的端口)上运行了两个单独的MVC5站点(单独的解决方案)。 其中之一是主机服务器,并且已安装SignalR。 主机的Startup.cs
如下所示:
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
// EnableJSONP = true
// EnableDetailedErrors = true
};
map.RunSignalR(hubConfiguration);
});
}
我只有一种方法在主机上建立一个集线器。 另一个MVC5站点是客户端,它具有以下JavaScript:
它调用的JS如下(相当标准):
$.connection.hub.logging = true;
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
var encodedName = $('<div />').text(name).html();
var encodedMsg = $('<div />').text(message).html();
$('#discussion').append('<li><strong>' + encodedName
+ '</strong>: ' + encodedMsg + '</li>');
};
$('#displayname').val(prompt('Enter your name:', ''));
$('#message').focus();
$.connection.hub.url = 'http://localhost:60601/signalr'; // <-- pointing to the host MVC5 site
$.connection.hub.start().done(function () {
console.log("Connected, transport = " + $.connection.hub.transport.name);
$('#sendmessage').click(function () {
chat.server.send($('#displayname').val(), $('#message').val());
$('#message').val('').focus();
});
}).fail(function (data) {
console.log('[Hub Start FAILED]' + data);
});
编辑发布日志
当我从上面使用代码时,在我的宿主站点上没有任何错误。 在客户端站点上,我在Chrome DevTools控制台中收到以下错误:
[18:06:41 GMT-0600 (Central Standard Time)] SignalR: Auto detected cross domain url.
[18:06:41 GMT-0600 (Central Standard Time)] SignalR: Client subscribed to hub 'chathub'.
[18:06:41 GMT-0600 (Central Standard Time)] SignalR: Negotiating with 'http://localhost:60601/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&clientProtocol=1.3'.
MLHttpRequest cannot load http://localhost:60601/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&clientProtocol=1.3&_=1386201997462. The 'Access-Control-Allow-Origin' header contains the invalid value 'http://localhost:50709, *'. Origin 'http://localhost:50709' is therefore not allowed access.
SignalR error: Error: Error during negotiation request.
[18:06:41 GMT-0600 (Central Standard Time)] SignalR: Stopping connection.
如果我通过添加参数来更改客户端javascript中集线器的开头,例如$.connection.hub.start({ jsonp: true, transport: 'webSockets' })
(如果我未将webSockets指定为传输器,则SignalR成功使用longpolling传输),然后出现以下错误日志。
客户端(Chrome DevTools控制台)
[18:06:41 GMT-0600 (Central Standard Time)] SignalR: Auto detected cross domain url.
[18:06:41 GMT-0600 (Central Standard Time)] SignalR: Client subscribed to hub 'chathub'.
[18:12:16 GMT-0600 (Central Standard Time)] SignalR: Negotiating with 'http://localhost:60601/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&clientProtocol=1.3'
[18:12:17 GMT-0600 (Central Standard Time)] SignalR: Connecting to websocket endpoint 'ws://localhost:60601/signalr/connect?transport=webSockets&connectionToken=GzcGbVs35BV0AFtJ2%2BJQqEYlQfW6ejf6CJ8QI73zfG8OsonD0LIzDmtzNBWM6jSHiD0ptuStjmyOKTpszMFJOgVZoBLuYN08TYx1WUbdNqKDLRZ35Vozmk666%2F7x3rjgowmXhTjX0pVlx8nDY%2FWrpA%3D%3D&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&tid=4'
[18:12:17 GMT-0600 (Central Standard Time)] SignalR: Websocket opened.
[18:12:22 GMT-0600 (Central Standard Time)] SignalR: webSockets timed out when trying to connect.
[18:12:22 GMT-0600 (Central Standard Time)] SignalR: Closing the Websocket.
SignalR error: Error: No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.
[18:12:22 GMT-0600 (Central Standard Time)] SignalR: Stopping connection.
[18:12:22 GMT-0600 (Central Standard Time)] SignalR: Fired ajax abort async = true.
和主机端(在VS2013输出窗口中):
SignalR.Transports.TransportHeartBeat Information: 0 : Connection 3e856309-8396-481e-8d32-b4085a93985f is New.
SignalR.Transports.WebSocketTransport Information: 0 : CloseSocket(3e856309-8396-481e-8d32-b4085a93985f)
SignalR.Transports.TransportHeartBeat Verbose: 0 : 3e856309-8396-481e-8d32-b4085a93985f is dead
SignalR.Transports.WebSocketTransport Information: 0 : Abort(3e856309-8396-481e-8d32-b4085a93985f)
SignalR.Transports.TransportHeartBeat Information: 0 : Removing connection 3e856309-8396-481e-8d32-b4085a93985f
SignalR.Transports.WebSocketTransport Information: 0 : End(3e856309-8396-481e-8d32-b4085a93985f)
SignalR.Transports.WebSocketTransport Verbose: 0 : DrainWrites(3e856309-8396-481e-8d32-b4085a93985f)
SignalR.Transports.WebSocketTransport Information: 0 : CompleteRequest (3e856309-8396-481e-8d32-b4085a93985f)
我在禁用了Chrome的网络安全模式下启动了宿主站点,而在Chrome上通常在了客户端站点,但是仍然收到CORS错误,并且连接断开了。
我在禁用了Chrome的网络安全模式下启动了客户端站点,而在Chrome上通常在了主机站点,并且没有遇到CORS问题,并且连接正常。
(如果两个站点也都在禁用Chrome的网络安全模式下运行,效果很好,但这并不奇怪)
当主机禁用安全性而客户端没有禁用安全性时,我希望不会遇到任何CORS问题-并非相反。 为什么会这样?
问题似乎出在您的Access-Control-Allow-Origin
标头上。
map.UseCors(CorsOptions.AllowAll);
上一行应使对SignalR CORS请求的每个响应都具有以下标头:
Access-Control-Allow-Origin: (request origin)
在您的情况下,(请求源)应为http://localhost:50709
,但应为http://localhost:50709, *
根据以下日志输出判断:
[18:06:41 GMT-0600 (Central Standard Time)] SignalR: Negotiating with 'http://localhost:60601/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&clientProtocol=1.3'.
HTMLHttpRequest cannot load http://localhost:60601/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&clientProtocol=1.3&_=1386201997462.
The 'Access-Control-Allow-Origin' header contains the invalid value 'http://localhost:50709, *'. Origin 'http://localhost:50709' is therefore not allowed access.
SignalR error: Error: Error during negotiation request.
这很可能是由类似于web.config中的以下内容引起的:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
或者,您的中间件代码中可能类似于以下内容:
Response.AppendHeader("Access-Control-Allow-Origin", "*");
无论哪种方式,由于您已经在使用map.UseCors(CorsOptions.AllowAll);
您不应在其他地方设置Access-Control-Allow-Origin
标头。
最后,我知道您可能只是出于调试目的而这样做,但是像这样启动连接: $.connection.hub.start({ jsonp: true, transport: 'webSockets' })
可能不是最好的主意。
使用这些设置,协商请求(以及任何长轮询请求)将始终使用JSONP而不是CORS发出。 当您无法使CORS正常工作时,这可能很有意义,但是如果您可以使CORS正常工作,则应该改用它,而不要启用JSONP,因为CORS允许进行更细粒度的访问控制配置。
如果设置EnableJSONP
到真正的服务器上,您允许JS代码在任何网站上运行,无论你设置你的访问SignalR服务CorsOptions
来。
如果您决定在服务器上保持启用JSONP,则没有理由在传递给hub.start
的配置对象中指定jsonp: true
,因为SignalR应该回退并在CORS请求失败时尝试使用JSONP。
指定transport: 'webSockets'
。 默认情况下,SignalR将尝试首先使用WebSocket传输(如果可用)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.