, поэтому у меня есть .net core (2.1) API, который использует токены JWT для аутентификации. Я могу войти в систему и успешно выполнять аутентифицированные звонки.
Я использую React (16.6.3) для клиента, который работает с кодом JWT и выполняет аутентифицированные вызовы API.
Я пытаюсь добавить концентраторы сигналов на сайт. Если я не помещу атрибут [Authorize] в класс концентратора. Я могу подключаться, отправлять и получать сообщения (на данный момент это базовый чатуб).
когда я добавляю атрибут [Authorize] в класс, приложение React сделает HttpPost равным example.com/hubs/chat/negotiate
. Я бы получил 401
код состояния. заголовок Authorization: Bearer abc.....
будет пропущен.
Чтобы построить концентратор в React, я использую:
const hubConn = new signalR.HubConnectionBuilder()
.withUrl(`${baseUrl}/hubs/chat`, { accessTokenFactory: () => jwt })
.configureLogging(signalR.LogLevel.Information)
.build();
где переменная jwt
является токеном.
У меня есть некоторые настройки для аутентификации:
services.AddAuthentication(a =>
{
a.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
a.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.SaveToken = false;
options.Audience = jwtAudience;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtIssuer,
ValidAudience = jwtAudience,
RequireExpirationTime = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtKey)),
};
// We have to hook the OnMessageReceived event in order to
// allow the JWT authentication handler to read the access
// token from the query string when a WebSocket or
// Server-Sent Events request comes in.
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var authToken = context.Request.Headers["Authorization"].ToString();
var token = !string.IsNullOrEmpty(accessToken) ? accessToken.ToString() : !string.IsNullOrEmpty(authToken) ? authToken.Substring(7) : String.Empty;
var path = context.HttpContext.Request.Path;
// If the request is for our hub...
if (!string.IsNullOrEmpty(token) && path.StartsWithSegments("/hubs"))
{
// Read the token out of the query string
context.Token = token;
}
return Task.CompletedTask;
}
};
});
событие OnMessageReceived
получает удар, а context.Token
получает значение токена JWT.
Я не могу понять, что я делаю неправильно, чтобы иметь возможность делать аутентифицированные вызовы для ядра сигнализатора.
решение
Я обновил свой код для использования 2.2 (не уверен, действительно ли это требовалось).
, поэтому я потратил некоторое время на просмотр исходного кода и примеров внутри:
https://github.com/aspnet/AspNetCore
У меня была проблема с Signalr CORS, которая была решена с помощью:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.SetIsOriginAllowed((host) => true) //allow all connections (including Signalr)
);
});
важной частью является .SetIsOriginAllowed((host) => true)
Это позволяет всем соединениям как для веб-сайта, так и для доступа к сигналам.
Я не добавил
services.AddAuthorization(options =>
{
options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, policy =>
{
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
policy.RequireClaim(ClaimTypes.NameIdentifier);
});
});
Я только использовал services.AddAuthentication(a =>
Я взял следующее непосредственно из образцов в github
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
if (!string.IsNullOrEmpty(accessToken) &&
(context.HttpContext.WebSockets.IsWebSocketRequest || context.Request.Headers["Accept"] == "text/event-stream"))
{
context.Token = context.Request.Query["access_token"];
}
return Task.CompletedTask;
}
};
Не уверен, нужно ли это в атрибуте, но то же самое использовал его в своих хабах
[Authorize(JwtBearerDefaults.AuthenticationScheme)]
из-за этого я не смог подключить несколько веб-сайтов и консольных приложений и общаться через сигнализатор.