5

サーバーが ASP.NET WebAPI でホストされているときに、SignalR で認証を有効にしたいと考えています。OAuth ベアラー認証を使用しており、クライアントは AngularJS です。

クライアント側では、もともと HTTP ヘッダーを介してベアラー トークンを渡し、WebAPI とうまく連携します。しかし、SignalR JavsScript は HTTP ヘッダーの追加をサポートconnectionしていないため (WebSocket が HTTP ヘッダーの指定をサポートしていないためです)、次のようなコードを使用してクエリ文字列を介して Bearer トークンを渡す必要があります。self.connection.qs = { Bearer: 'xxxxxx' };

問題は WebAPI 側にあり、SignalR は常に 401 Unauthorized を返しました。

以下は、私が WebAPI 側で行ったことです。

1 に指定OAuthBearerAuthenticationOptions.Providerしました。これは、クエリ文字列から Bearer トークンを取得できる、QueryStringEnabledOAuthBearerAuthenticationProvider継承して作成したクラスです。OAuthBearerAuthenticationProvider以下のようにコードします。

    public class QueryStringEnabledOAuthBearerAuthenticationProvider : OAuthBearerAuthenticationProvider
    {
        プライベート読み取り専用文字列 _name;

        public QueryStringEnabledOAuthBearerAuthenticationProvider()
            : this(OAuthDefaults.AuthenticationType)
        {
        }

        public QueryStringEnabledOAuthBearerAuthenticationProvider(文字列名)
        {
            _name = 名前;
        }

        public override Task RequestToken(OAuthRequestTokenContext コンテキスト)
        {
            // 可能であれば、基本クラス (ヘッダー) からトークンを読み取ろうとします
            base.RequestToken(context).Wait();
            if (string.IsNullOrWhiteSpace(context.Token))
            {
                // クエリ文字列からトークンを読み取ろうとする
                var トークン = context.Request.Query.Get(_name);
                if (!string.IsNullOrWhiteSpace(トークン))
                {
                    context.Token = トークン;
                }
            }
            Task.FromResult(null) を返します。
        }
    }

そしてWebAPI起動時に以下のように登録。

            var オプション = 新しい OAuthBearerAuthenticationOptions
            {
                AuthenticationMode = AuthenticationMode.Active、
                認証タイプ = 認証タイプ、
                プロバイダ = 新しい QueryStringEnabledOAuthBearerAuthenticationProvider(),
                AccessTokenFormat = _accessTokenFormat,
            };
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(新しい HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
            app.UseOAuthBearerAuthentication(オプション);

2, SignalR の部分で、以下のように authorize 属性を作成しました。ブレークポイントを追加するために使用するためだけに何も変更されていません。

    public class BearerAuthorizeAttribute : AuthorizeAttribute
    {
        public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
        {
            base.AuthorizeHubConnection(hubDescriptor, request); を返します。
        }

        public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool applyToMethod)
        {
            base.AuthorizeHubMethodInvocation(hubIncomingInvokerContext, applyToMethod); を返します。
        }
    }

WebAPIの起動時にも登録しました。

            app.Map("/signalr", マップ =>
                {
                    // SignalR の前に CORS ミドルウェアを実行するようにセットアップします。
                    // デフォルトでは、これはすべてのオリジンを許可します。あなたはできる
                    // オリジンおよび/または http 動詞のセットを設定します
                    // 異なるポリシーで cors オプションを提供します。
                    map.UseCors(CorsOptions.AllowAll);
                    var hubConfiguration = 新しい HubConfiguration
                    {
                        // 以下の行のコメントを外すと、JSONP を有効にできます。
                        // JSONP リクエストは安全ではありませんが、一部の古いブラウザー (および一部の
                        // IE のバージョン) では、クロスドメインで動作するために JSONP が必要です
                        // EnableJSONP = true
                        EnableJavaScriptProxies = false
                    };
                    // SignalR パイプラインを実行します。MapSignalR を使用していません
                    // このブランチは既に "/signalr" の下で実行されているため
                    // 道。
                    map.RunSignalR(hubConfiguration);
                    // すべてのハブに認証を要求する
                    var authorizer = new BearerAuthorizeAttribute();
                    var module = new AuthorizeModule(オーソライザー、オーソライザー);
                    GlobalHost.HubPipeline.AddModule(モジュール);
                });

SignalR が接続されたときQueryStringEnabledOAuthBearerAuthenticationProvider.RequestTokenに呼び出され、Bearer トークンが正常に取得されたことがわかりました。ただし、SignalRBearerAuthorizeAttribute.AuthorizeHubConnectionが呼び出されたとき、パラメーターrequest.Userはまだ認証されていません。そのため、401 が返されました。

何が間違っていたのか、誰かにアイデアを教えてもらえますか、ありがとう。

4

2 に答える 2