使用ajaxSetup beforeSend进行Basic Auth会破坏SignalR连接

Ste*_*vie 7 ajax authorization basic-authentication signalr asp.net-web-api

我有一个使用Basic Auth保护的WebApi,它使用AuthorizationFilterAttribute应用于整个Api.我还在我的几个Api控制器上安装了SignalR Hub.

除此之外,我还有一个使用WebApi的网页.该网页主要是用Backbone编写的,所以为了调用我的安全WebApi,我添加了以下jquery

$.ajaxSetup({
    beforeSend: function (jqXHR, settings) {
        jqXHR.setRequestHeader('Authorization', 'Basic ' + Token);
        return true;
    }
});
Run Code Online (Sandbox Code Playgroud)

这适用于与我的Api控制器通信,但添加上述代码已断开与SignalR Hub的连接,具体为:

XMLHttpRequest cannot load http://localhost:50000/signalr/negotiate?_=1366795855194. 
Request header field Authorization is not allowed by Access-Control-Allow-Headers. 
Run Code Online (Sandbox Code Playgroud)

删除jqXHR.setRequestHeader()线路将恢复我的SignalR Hub连接,但会中断Api呼叫.

鉴于上述情况,我可以做一些hacky并且只设置请求标头,如果发出的请求不是/ signalr但是感觉很脏......

这有更干净的方法吗?

我只是做些傻事吗?有没有其他人参加过此活动?

Ste*_*vie 7

我之前没有提到的是我有一个DelegatingHandler,它将正确的Headers发送回任何进入我的WebApi的请求.这适用于任何对WebApi的请求,但我错误地认为这也适用于SignalR请求.

由于SignalR依赖于几种不同的传输方法,因此假设我首先可以访问授权标头似乎是不合理的 - 例如,它们不是所有WebSockets实现的要求(参见此处)

我目前的解决方案是使用SignalR的HubPipeline(详见此处).使用这个,我相信我可以在查询字符串中传递Basic Auth凭证,并编写一个单独的模块来处理SignalR请求的授权:


传递查询字符串

$.connection.hub.qs = "auth=" + MyBase64EncodedAuthString;
Run Code Online (Sandbox Code Playgroud)

过滤器

public class SignalrBasicAuthFilterAttribute: Attribute, IAuthorizeHubConnection {

    public bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) {
      var authString = request.QueryString["auth"];

      // ... parse, authorize, etc ...

      return true;
    }

}
Run Code Online (Sandbox Code Playgroud)

注册过滤器

var globalAuthorizer = new SignalrBasicAuthFilterAttribute();
GlobalHost.HubPipeline.AddModule(new AuthorizeModule(globalAuthorizer, globalAuthorizer));
Run Code Online (Sandbox Code Playgroud)

另外...

请注意,因为使用SignalR请求发送Authorization标头不是一个可靠的假设,出于上述原因,我仍在过滤$ .ajaxSetup以仅影响非SignalR请求:

$.ajaxSetup({
    beforeSend: function (jqXHR, settings) {
        if (settings.url.indexOf("/signalr") == -1)
            jqXHR.setRequestHeader('Authorization', 'Basic ' + Token);
        return true;
    }
});
Run Code Online (Sandbox Code Playgroud)

在这样做时,我将离开SignalrBasicAuthFilterAttribute类,以承担授权SignalR请求的全部责任.


进一步阅读: