У меня есть собственный сервер сигнализации (концентратор) в службе Windows.Доступ к этому хабу могут получить только аутентифицированные пользователи или клиенты с токеном JWT.Вот настройки для моего класса Startup and Program
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.SetIsOriginAllowed((host) => true));
});
services.AddOptions();
services.AddDbContextPool<MusterEFContext>
(options =>
options.UseLazyLoadingProxies().UseSqlServer(Configuration["Database:Connection"])
);
//Code for transient services, etc.
var jwtConfig = new JwtAuthentication();
Configuration.GetSection("JwtAuthentication").Bind(jwtConfig);
services.AddIdentity<MusterUser, IdentityRole>(options =>
{
options.Password.RequiredLength = 8;
options.User.RequireUniqueEmail = true;
options.Password.RequireDigit = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
})
.AddEntityFrameworkStores<MusterEFContext>()
.AddSignInManager<SignInManager<MusterUser>>()
.AddUserManager<UserManager<MusterUser>>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddDefaultTokenProviders();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.IncludeErrorDetails = true;
options.ClaimsIssuer = jwtConfig.ValidIssuer;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtConfig.ValidIssuer,
ValidAudience = jwtConfig.ValidAudience,
RoleClaimType = ClaimTypes.Role,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SecurityKey))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
// If the request is for our hub...
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/realtime")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("TenantPolicy", policy => policy.RequireRole("Tenant"));
options.AddPolicy("HostPolicy", policy => policy.RequireRole("Host"));
options.AddPolicy("AdminPolicy", policy => policy.RequireRole("Admin"));
options.AddPolicy("DashboardPolicy", policy => policy.RequireAssertion(x => (
x.User.IsInRole("Host") || x.User.IsInRole("Tenant")
)));
});
services.AddHangfire(x => x.UseSqlServerStorage(Configuration["Database:Hangfire"]));
services.AddHangfireServer();
services.AddSignalR();
}
Вот остальные классы запуска
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors("CorsPolicy");
app.UseAuthentication();
app.UseHangfireDashboard();
app.UseSignalR(config =>
{
config.MapHub<Muster.Core.Hubs.ChatHub>("/realtime");
});
}
Проблема, с которой я сталкиваюсь, заключается в том, когда я развертываю и устанавливаю этот сервис в моей Stagingserver
В этой строке, где я пытаюсь получить утверждение текущего пользователя из контекста, всегда возвращается значение null
public override async Task OnConnectedAsync()
{
try
{
string userId = (Context.User.Identity as ClaimsIdentity).FindFirst(ClaimTypes.Name).Value; //This line always breaks because Context.User is null or empty i.e no claims.
Logger.LogInformation($"User Id : {userId}");
if (userId != null)
{
string connectionId = Context.ConnectionId;
var user = _userManager.FindByIdAsync(userId);
if (user.Result != null)
{
await _messageService.AddConnection(connectionId, userId, Context.GetHttpContext().Request.Headers["User-Agent"]);
}
await base.OnConnectedAsync();
}
else
{
Logger.LogWarning("Could not get user id for specified claim");
throw new Exception("User Id is Null");
}
// await base.OnConnectedAsync();
}
catch (Exception ex)
{
Logger.LogError("An error occured while connecting to this hub");
Logger.LogError(ex.Message);
Logger.LogError(ex.StackTrace);
Logger.LogError(ex.TargetSite.ToString());
throw;
}
}```
По какой-то причине я не могу получить ни одно из утверждений, удерживаемыхпользователь или клиент, который пытается подключиться к концентратору на моем промежуточном сервере, но это прекрасно работает на моем компьютере.вот фрагмент из моего сигнализатора Javascript-клиента
this.connection = new signalR.HubConnectionBuilder()
.withUrl(config.SignalRUrl, { accessTokenFactory: () => { return auth.token(); } })
.configureLogging(signalR.LogLevel.Trace)
.build();