サーバーが 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 が返されました。
何が間違っていたのか、誰かにアイデアを教えてもらえますか、ありがとう。