我有一个 SignalR Core 集线器,它依赖于服务。该服务本身有其自己的依赖项,其中之一需要访问当前的 ClaimsPrincipal。
我知道,我可以使用 Context.User 属性访问集线器内的 ClaimsPrincipal 并将其作为参数传递给服务,服务也可以将其作为参数传递等等。但我真的不喜欢通过将这种环境信息作为参数传递来污染服务 API。
我尝试使用 IHttpContextAccessor,如下所述:https://learn.microsoft.com/en-us/aspnet/core/migration/claimsprincipal-current?view=aspnetcore-2.2 这似乎适用于简单的 SignalR 设置,但它不适用于 Azure SignalR 服务,而这将是我们的生产设置。
有没有一种可靠的方法可以让 ClaimsPrincipal 脱离中心,同时适用于简单的本地设置和 Azure SignalR 服务?
最佳答案
在当前的 SignalR 版本 (1.1.0) 中不支持此功能。我创建了一个功能请求:https://github.com/dotnet/aspnetcore/issues/18657但被拒绝了。最终,我这样做了:
services.AddSingleton(typeof(HubDispatcher<>), typeof(HttpContextSettingHubDispatcher<>));
public class HttpContextSettingHubDispatcher<THub> : DefaultHubDispatcher<THub> where THub : Hub
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpContextSettingHubDispatcher(IServiceScopeFactory serviceScopeFactory, IHubContext<THub> hubContext,
IOptions<HubOptions<THub>> hubOptions, IOptions<HubOptions> globalHubOptions,
ILogger<DefaultHubDispatcher<THub>> logger, IHttpContextAccessor httpContextAccessor) :
base(serviceScopeFactory, hubContext, hubOptions, globalHubOptions, logger)
{
_httpContextAccessor = httpContextAccessor;
}
public override async Task OnConnectedAsync(HubConnectionContext connection)
{
await InvokeWithContext(connection, () => base.OnConnectedAsync(connection));
}
public override async Task OnDisconnectedAsync(HubConnectionContext connection, Exception exception)
{
await InvokeWithContext(connection, () => base.OnDisconnectedAsync(connection, exception));
}
public override async Task DispatchMessageAsync(HubConnectionContext connection, HubMessage hubMessage)
{
switch (hubMessage)
{
case InvocationMessage _:
case StreamInvocationMessage _:
await InvokeWithContext(connection, () => base.DispatchMessageAsync(connection, hubMessage));
break;
default:
await base.DispatchMessageAsync(connection, hubMessage);
break;
}
}
private async Task InvokeWithContext(HubConnectionContext connection, Func<Task> action)
{
var cleanup = false;
if (_httpContextAccessor.HttpContext == null)
{
_httpContextAccessor.HttpContext = connection.GetHttpContext();
cleanup = true;
}
await action();
if (cleanup)
{
_httpContextAccessor.HttpContext = null;
}
}
}
关于asp.net-core - 如何在 Hub 外部获取 SignalR 核心中的当前 ClaimsPrincipal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59952279/