在使用OWIN自托管SignalR时出现CORS问题,只有在我尝试启用身份验证时才会发生。
我在网络浏览器中收到的错误是:
XMLHttpRequest无法加载http://.../signalr/negotiate?[snip] Access-Control-Allow-Origin
不允许来源...
仅当我使用this answer中的方法在我的自托管服务器中启用身份验证时才会发生这种情况:
public void Configuration(IAppBuilder app)
{
var listener = (HttpListener)app.Properties[typeof(HttpListener).FullName];
listener.AuthenticationSchemes = AuthenticationSchemes.Ntlm;
app.MapHubs(new HubConfiguration { EnableCrossDomain = true });
}
如果我注释掉AuthenticationSchemes
行,那么CORS就可以了(我已经检查了these instructions中的所有内容)。如果我使用其他身份验证方案而不是NTLM,我会遇到同样的问题。
使用Fiddler检查发生了什么,未启用身份验证我看到从服务器返回的必要CORS标头:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:[我的服务器]
但是,一旦启用身份验证,我就会得到一个401响应,但是缺少这些头。所有请求都有必要的Origin
标题。
检查了SignalR source code后,它看起来像是设置了标头,但可能启用了身份验证,HttpListener
正在发送初始401响应而不会点击此代码。
所以我认为我的问题是:如何让HttpListener
在其身份验证协议的协商中包含Access-Control-Allow-Origin
标头?
答案 0 :(得分:4)
通过允许预检请求匿名访问,我获得了NTLM身份验证,以便与OWIN中自托管的跨域signalR一起使用。
需要做的是创建一个委托,用于选择查找预检请求标头的身份验证方案,并通过匿名方式允许这些方案。所有其他请求将使用NTLM。
public void Configuration(IAppBuilder appBuilder)
{
var listener = (HttpListener)appBuilder.Properties[typeof(HttpListener).FullName];
listener.AuthenticationSchemeSelectorDelegate += AuthenticationSchemeSelectorDelegate;
}
private AuthenticationSchemes AuthenticationSchemeSelectorDelegate(HttpListenerRequest httpRequest)
{
if (httpRequest.Headers.Get("Access-Control-Request-Method")!=null)
return AuthenticationSchemes.Anonymous;
else
return AuthenticationSchemes.Ntlm;
}
答案 1 :(得分:3)
我认为您正在使用Chrome,这非常无益地告诉您这些标题丢失了,这就是问题,实际上您可能只是忘记设置XMLHttpRequest
' s withCredentials
属性true
。
如果您正在使用jQuery,则可以对以下所有请求执行此操作:
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
options.xhrFields = { withCredentials: true };
});
您还需要使用OPTIONS
请求做正确的事情,如在另一个答案中那样。