【问题标题】:Using ajaxSetup beforeSend for Basic Auth is breaking SignalR connection使用 ajaxSetup beforeSend 进行基本身份验证会破坏 SignalR 连接
【发布时间】:2013-04-26 19:06:38
【问题描述】:

我有一个使用 Basic Auth 保护的 WebApi,它使用 AuthorizationFilterAttribute 应用于整个 Api。我的几个 Api 控制器上也有 SignalR 集线器。

除此之外,我还有一个使用我的 WebApi 的网页。网页大部分是用 Backbone 编写的,所以为了调用我的安全 WebApi,我添加了以下 jquery

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

这适用于与我的 Api 控制器进行通信,但添加上述代码会破坏与我的 SignalR 集线器的连接,具体而言:

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

删除 jqXHR.setRequestHeader() 行会恢复我的 SignalR Hub 连接,但会中断 Api 调用。

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

有没有更干净的方法解决这个问题?

我只是在做一些傻事吗?有没有其他人遇到过这个?

【问题讨论】:

    标签: ajax asp.net-web-api authorization signalr basic-authentication


    【解决方案1】:

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

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

    我目前的解决方案是使用 SignalR 的 HubPipeline (detailed here)。使用它,我相信我可以在查询字符串中传递基本身份验证凭据并编写一个单独的模块来处理 SignalR 请求的授权:


    传递查询字符串

    $.connection.hub.qs = "auth=" + MyBase64EncodedAuthString;
    

    过滤器

    public class SignalrBasicAuthFilterAttribute: Attribute, IAuthorizeHubConnection {
    
        public bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) {
          var authString = request.QueryString["auth"];
    
          // ... parse, authorize, etc ...
    
          return true;
        }
    
    }
    

    注册过滤器

    var globalAuthorizer = new SignalrBasicAuthFilterAttribute();
    GlobalHost.HubPipeline.AddModule(new AuthorizeModule(globalAuthorizer, globalAuthorizer));
    

    另外...

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

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

    在此过程中,我将让 SignalrBasicAuthFilterAttribute 类承担授权 SignalR 请求的全部责任。


    进一步阅读:

    【讨论】:

      【解决方案2】:

      我认为该问题的真正解决方案是确保“授权”是从“协商”请求的 signalR 响应返回的允许标头(访问控制允许标头)的一部分。

      您可以像这种可能性一样在 web.config 中注册标头。

      <httpProtocol>
        <customHeaders>
          <add name="Access-Control-Allow-Headers" value="Authorization" />
        </customHeaders>
      </httpProtocol>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-12
        • 2017-06-13
        • 2013-05-30
        • 2012-08-22
        • 2016-05-31
        • 2017-10-06
        • 2013-09-14
        • 2010-12-11
        相关资源
        最近更新 更多