SignalR跨域连接与自托管和身份验证

时间:2013-07-05 09:04:20

标签: signalr cors owin

在使用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标头?

2 个答案:

答案 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请求做正确的事情,如在另一个答案中那样。