SignalR дает мне 404 при попытке подключения для некоторых пользователей. URL-адреса такие же, за исключением access_token.
Он стабильно воспроизводится для каждого пользователя (я имею в виду, что некоторые пользователи стабильно работают нормально, некоторые пользователи стабильно 404).
access_token проанализировал jwt diff (слева пользователь в порядке, справа — 404):
Я провел трассировку журналов и получил следующее: Для пользователя OK:
Для пользователя, получившего ошибку 404:
Примечание. URL-адреса под черными квадратами одинаковы.
Front End — это Angular 9 с пакетом "@microsoft/signalr": "^3.1.8"
, и вот код, который создает соединение:
private buildHub(): HubConnection {
console.log(this.authService.accessToken);
let builder = new HubConnectionBuilder()
.withAutomaticReconnect()
.configureLogging(LogLevel.Information)
.withUrl('ws/notificationHub', {
accessTokenFactory: () => this.authService.accessToken
});
if (this.debugMode) {
builder = builder.configureLogging(LogLevel.Trace);
}
return builder.build();
}
Бэкэнд использует следующий код в Startup для настройки концентратора signalR:
In public void ConfigureServices(IServiceCollection services)
:
services.AddSignalR()
.AddJsonProtocol(options =>
{
options.PayloadSerializerSettings.ContractResolver = new DefaultContractResolver();
});
In public void Configure(IApplicationBuilder app, IHostingEnvironment env)
:
app.UseSignalR(route =>
{
route.MapHub<NotificationHub>("/ws/notificationHub");
});
Также мы используем пользовательскую аутентификацию, поэтому у нас есть атрибут Authorize
для класса Hub:
[Authorize]
public class NotificationHub: Hub<INotificationHubClient>
и этот код в public void ConfigureServices(IServiceCollection services)
:
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = identityServerSettings.Url;
options.Audience = identityServerSettings.ApiScopeName;
options.RequireHttpsMetadata = identityServerSettings.RequireHttpsMetadata;
options.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/ws"))
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
К сожалению, у меня нет полного доступа к среде, где это воспроизводимо, но я могу запросить просмотр каких-либо настроек или попытаться внести некоторые изменения.
Что еще я могу попробовать, чтобы устранить проблему?
ОБНОВЛЕНИЕ: переговоры подходят для обоих пользователей.