在 SignalR Hub 的 OnConnected/OnDisconnected 中注入租户信息

问题描述 投票:0回答:1

有一个多租户 SaaS 应用程序,我想在 SignalR Hub 的

tenantId
/
OnConnectedAsync
挂钩中为每个
OnDisconnectedAsync
创建组。

问题是

ITenancyContext<ApplicationTenant>
被注册为范围服务,这意味着它仅在请求范围内可用。在 SignalR hub 的上下文中,它与请求无关,因此不可用。

那么我该如何让它可用呢?授权它并以某种方式丰富声明?

public sealed class NotificationHub : Hub
{
    readonly ILogger<NotificationHub> _logger;
    readonly Guid _tenantId;

    public NotificationHub(ILogger<NotificationHub> logger, ITenancyContext<ApplicationTenant> tenancyContext) => (_logger, _tenantId) = (logger, tenancyContext.Tenant.Id);

    public override async Task OnConnectedAsync()
    {
        await JoinGroup(_tenantId.ToString());
        _logger.LogInformation("{ConnectionId} has connected to the hub. TenantId: {TenantId}", Context.ConnectionId, _tenantId);
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        await LeaveGroup(_tenantId.ToString());
        _logger.LogInformation("{ConnectionId} was disconnected from the hub. TenantId: {TenantId}", Context.ConnectionId, _tenantId);
        await base.OnDisconnectedAsync(exception);
    }

    Task JoinGroup(string groupName) => Groups.AddToGroupAsync(Context.ConnectionId, groupName);

    Task LeaveGroup(string groupName) => Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
}
c# .net asp.net-core signalr signalr-hub
1个回答
0
投票

我认为我们可以创建一个中间件来实现它。在这个中间件中注入

ITenancyContext<ApplicationTenant>
,我们称之为
TenantMiddleware
.

public class TenantMiddleware
{
    private readonly ITenancyContext<ApplicationTenant> _tenancyContext;

    public TenantMiddleware(ITenancyContext<ApplicationTenant> tenancyContext)
    {
        _tenancyContext = tenancyContext;
    }

    public async Task InvokeAsync(HttpContext context, Func<Task> next)
    {
        var user = context.User.Identity as ClaimsIdentity;
        if (user != null)
        {
            var TenantId= _tenancyContext.Tenant.Id;
            user.AddClaim(new Claim("TenantId", TenantId.ToString()));
        }

        await next();
    }
}

然后我们可以在您的

NotificationHub
课上使用它。

public override async Task OnConnectedAsync()
{
    // Get TenantId like below.
    var user = Context.User.Identity as ClaimsIdentity;
    var tenantIdClaim = user?.FindFirst("TenantId");
    _tenantId = tenantIdClaim != null ? Guid.Parse(tenantIdClaim.Value) : Guid.Empty;
    ...
    await JoinGroup(_tenantId.ToString());
    _logger.LogInformation("{ConnectionId} has connected to the hub. TenantId: {TenantId}", Context.ConnectionId, _tenantId);
    await base.OnConnectedAsync();
}
© www.soinside.com 2019 - 2024. All rights reserved.