使用全局查询过滤器时,当我尝试获取角色以更新声明时,租户 ID 为空

When using Global Query Filters, tenant Id is null when I try to get roles to update the claims

我正在尝试在我正在处理的应用程序中设置多租户。我添加了全局查询过滤器并按照建议实施了 TenantProvider here。请注意我列出的示例中的这段代码:

public interface ITenantProvider
{
    Guid GetTenantId();
}
 
public class DummyTenantProvider : ITenantProvider
{
    public Guid GetTenantId()
    {
        return Guid.Parse("069b57ab-6ec7-479c-b6d4-a61ba3001c86");
    }
}

在我的例子中,我实现了从 HttpContextAccessor.HttpContext.User.GetTenantId() 获取 tenantId 的租户提供程序,而不是 DummyTenantProvider。我知道 HttpContextAccessor.HttpContext.User 的类型是 ClaimsPrincipal,所以我添加了接受 this ClaimsPrincipal 作为参数和 returns tenantId:

的附加方法
public static string GetTenantId(this ClaimsPrincipal principal)
{
    return principal.FindFirstValue("tenant");
}

此外,我已经使用 JWT 令牌实现了 Api 身份验证。在Startup.cs中,我添加了这样的认证注册:

services.AddAuthentication(options =>
{
    // some code that is not relevant
}).AddJwtBearer(options =>
{
    // some code that is not relevant

    options.Events = new JwtBearerEvents
    {
        OnTokenValidated = async context =>
        {
            // here I get the needed service and from that service, I get the data that I need for Claims (Roles are needed)
            var claims = new List<Claim>
                            {
                                new Claim(ClaimTypes.Role, JsonConvert.SerializeObject(roles)),
                            };
            var appIdentity = new ClaimsIdentity(claims);
            context.Principal.AddIdentity(appIdentity);
        },
    };
});

现在,我遇到的问题是,当我发出 HTTP 请求时,该请求的目标是控制器中为用户获取角色的方法(该方法使用的服务与我在上面的代码)调试代码时,首先调用 OnTokenValidated 并填充用户角色并将其添加到声明中,然后调用控制器中的方法。当 OnTokenValidated 调用服务并执行对数据库的请求时(存储库中的简单“dbContext.Roles.ToListAsync()”),将应用全局查询过滤器,并且应将 tenantId 添加到该数据库请求中.但是当应用全局过滤器时,GetTenantId 方法中的 tenantId 为 null,代码抛出 ArgumentNullException 错误。我想不通的是为什么 tenantId 为空。我的假设是,当从 OnTokenValidated 调用服务时,那不是 HTTP 请求的一部分,然后 HttpContextAccessor.HttpContext 没有所需的值,但我不确定我是否没错。 对于我在这里做错了什么,我将不胜感激。 如果还需要其他任何东西来使事情更清楚,我很乐意编辑问题。 谢谢大家

对于任何需要解决方案的人,我能够通过使用 TokenValidatedContextStartup.cs 中添加租户 ID 作为新声明来解决此问题(因为我在 TokenValidatedContext在那一刻)。看起来像这样:

ctx.HttpContext.User.Identity?.AddClaim(New Claim('tenant'));

稍后在 Tenant Provider 中我可以访问此声明。