Сбой аутентификации SignalR при передаче «Bearer» через строку запроса
Я хотел бы включить аутентификацию в SignalR, когда сервер был размещен в ASP.NET WebAPI, где я использую аутентификацию OAuth Bearer, а клиент - AngularJS.
На стороне клиента я изначально передаю токен Bearer через HTTP-заголовок, и он хорошо работает с WebAPI. Но поскольку SignalR JavsScript не поддерживает добавление заголовков HTTP вconnection
(это потому, что WebSocket не поддерживает указание заголовков HTTP) Мне нужно передать токен Bearer через строку запроса, используя такой код, какself.connection.qs = { Bearer: 'xxxxxx' };
Проблема на стороне WebAPI, мой SignalR всегда возвращал 401 Несанкционированный.
Ниже то, что я сделал на стороне WebAPI.
1, я указалOAuthBearerAuthenticationOptions.Provider
вQueryStringEnabledOAuthBearerAuthenticationProvider
, который является классом, который я создал унаследованным отOAuthBearerAuthenticationProvider
который может получить токен Bearer из строки запроса. Код как ниже.
public class QueryStringEnabledOAuthBearerAuthenticationProvider : OAuthBearerAuthenticationProvider { private readonly string _name; public QueryStringEnabledOAuthBearerAuthenticationProvider() : this(OAuthDefaults.AuthenticationType) { } public QueryStringEnabledOAuthBearerAuthenticationProvider(string name) { _name = name; } public override Task RequestToken(OAuthRequestTokenContext context) { // try to read token from base class (header) if possible base.RequestToken(context).Wait(); if (string.IsNullOrWhiteSpace(context.Token)) { // try to read token from query string var token = context.Request.Query.Get(_name); if (!string.IsNullOrWhiteSpace(token)) { context.Token = token; } } return Task.FromResult(null); } }
И зарегистрировал это, как показано ниже, пока WebAPI был запущен.
var options = new OAuthBearerAuthenticationOptions { AuthenticationMode = AuthenticationMode.Active, AuthenticationType = AuthenticationType, Provider = new QueryStringEnabledOAuthBearerAuthenticationProvider(), AccessTokenFormat = _accessTokenFormat, }; config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); app.UseOAuthBearerAuthentication(options);
2, в части SignalR я создал атрибут авторизации, как показано ниже. Ничего не изменилось, только чтобы добавить точку останова.
public class BearerAuthorizeAttribute : AuthorizeAttribute { public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) { return base.AuthorizeHubConnection(hubDescriptor, request); } public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod) { return base.AuthorizeHubMethodInvocation(hubIncomingInvokerContext, appliesToMethod); } }
И зарегистрировал это, когда WebAPI также запустился.
app.Map("/signalr", map => { // Setup the CORS middleware to run before SignalR. // By default this will allow all origins. You can // configure the set of origins and/or http verbs by // providing a cors options with a different policy. map.UseCors(CorsOptions.AllowAll); var hubConfiguration = new HubConfiguration { // You can enable JSONP by uncommenting line below. // JSONP requests are insecure but some older browsers (and some // versions of IE) require JSONP to work cross domain // EnableJSONP = true EnableJavaScriptProxies = false }; // Run the SignalR pipeline. We're not using MapSignalR // since this branch already runs under the "/signalr" // path. map.RunSignalR(hubConfiguration); // Require authentication for all hubs var authorizer = new BearerAuthorizeAttribute(); var module = new AuthorizeModule(authorizer, authorizer); GlobalHost.HubPipeline.AddModule(module); });
Я обнаружил, когда SignalR подключил мойQueryStringEnabledOAuthBearerAuthenticationProvider.RequestToken
был вызван, и он успешно получил токен на предъявителя. Но тогда, когда SignalRBearerAuthorizeAttribute.AuthorizeHubConnection
был вызван параметрrequest.User
до сих пор не заверены. Так вернулось 401.
Может кто-нибудь дать мне несколько идей о том, что я не так сделал, спасибо.