7

我有一个使用基本身份验证保护的 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 调用。

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

有没有更清洁的方法来解决这个问题?

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

4

2 回答 2

7

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

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

我目前的解决方案是使用 SignalR 的 HubPipeline(在此处详述)。使用它,我相信我可以在查询字符串中传递基本身份验证凭据并编写一个单独的模块来处理 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 以仅影响非 SignalR请求:

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

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


延伸阅读:

于 2013-04-25T14:20:37.170 回答
1

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

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

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Headers" value="Authorization" />
  </customHeaders>
</httpProtocol>
于 2013-04-24T18:31:58.280 回答