7

AuthorizationFilterAttribute を使用して Api 全体に適用される Basic Auth で保護された WebApi があります。また、いくつかの Api コントローラーに SignalR ハブを配置しています。

これに加えて、WebApi を利用する Web ページがあります。Web ページは主に 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

前に言及しなかったのは、WebApi に着信するすべての要求に正しいヘッダーを返す DelegatingHandler があることです。これは、WebApi へのすべての要求に対して完全に機能しますが、これが SignalR 要求にも適用されると誤って想定していました。

SignalR はいくつかの異なるトランスポート メソッドに依存しているため、そもそも Authorization ヘッダーにアクセスできると仮定するのは合理的ではないようです。たとえば、それらはすべての WebSocket 実装の要件ではありません (こちらを参照) 。

私の現在の解決策は、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 応答から返される許可されたヘッダー (Access-Control-Allow-Headers) の一部であることを確認することだと思います。

この可能性と同じように、ヘッダーを web.config に登録できます。

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