【问题标题】:How to get the current ClaimsPrincipal in SignalR core outside of a Hub如何在集线器外的 SignalR 核心中获取当前的 ClaimsPrincipal
【发布时间】:2020-05-14 01:50:31
【问题描述】:

我有一个 SignalR Core 集线器,它依赖于服务。该服务本身有它自己的依赖项,其中一个需要访问当前的 ClaimsPrincipal。

我知道,我可以使用 Context.User 属性访问集线器内的 ClaimsPrincipal 并将其作为参数传递给服务,服务也可以将其作为参数传递等等。但我真的不喜欢通过将这种环境信息作为参数传递来污染服务 API。

我尝试使用 IHttpContextAccessor,如下所述:https://docs.microsoft.com/en-us/aspnet/core/migration/claimsprincipal-current?view=aspnetcore-2.2 这似乎适用于简单的 SignalR 设置,但不适用于 Azure SignalR 服务,这将是我们的生产设置。

是否有一种可靠的方法可以在集线器之外获取适用于简单本地设置和 Azure SignalR 服务的 ClaimsPrincipal?

【问题讨论】:

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


    【解决方案1】:

    在当前的 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;
            }
        }
    }
    

    【讨论】:

    • 我遇到了同样的问题。到目前为止,我只找到了这个解决方法,我在使用时遇到了麻烦。你安装了什么包?我得到'HubConnectionContext' does not contain a definition for 'GetHttpContext'
    • 在这个类中:docs.microsoft.com/en-us/dotnet/api/… nuget: Microsoft.AspNetCore.SignalR
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-24
    • 1970-01-01
    相关资源
    最近更新 更多