asp.net-core - 如何在 Hub 外部获取 SignalR 核心中的当前 ClaimsPrincipal

标签 asp.net-core asp.net-core-signalr azure-signalr

我有一个 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/

相关文章:

c# - ASP.NET Core 中的状态码 406( Not Acceptable )

c# - 在 ExceptionFilter 中访问 dbcontext

asp.net-core-signalr - .Net Core 3.1 SignalR 客户端 - 如何将 JWT token 字符串添加到 SignalR 连接配置?

asp.net-core - 我们可以在 ASP.NETCORE 应用程序中托管 ASP.NET SignalR v2.4.1 吗?

nginx - Nginx 背后的 SignalR - 获得 200 响应而不是 websocket 升级

c# - 为什么 Azure SignalR 不发送 Azure Functions 发布的消息?

Azure 函数在本地工作,但上传到 azure 后不起作用

asp.net - 混合自定义和默认模型绑定(bind)

debugging - IIS Express中的ASP.NET Core虚拟目录

c# - 有没有办法对连接到 Azure SignalR 的用户进行身份验证?