使用全局查询过滤器时,当我尝试获取角色以更新声明时,租户 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
没有所需的值,但我不确定我是否没错。
对于我在这里做错了什么,我将不胜感激。
如果还需要其他任何东西来使事情更清楚,我很乐意编辑问题。
谢谢大家
对于任何需要解决方案的人,我能够通过使用 TokenValidatedContext
在 Startup.cs
中添加租户 ID 作为新声明来解决此问题(因为我在 TokenValidatedContext
在那一刻)。看起来像这样:
ctx.HttpContext.User.Identity?.AddClaim(New Claim('tenant'));
稍后在 Tenant Provider 中我可以访问此声明。
我正在尝试在我正在处理的应用程序中设置多租户。我添加了全局查询过滤器并按照建议实施了 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
没有所需的值,但我不确定我是否没错。
对于我在这里做错了什么,我将不胜感激。
如果还需要其他任何东西来使事情更清楚,我很乐意编辑问题。
谢谢大家
对于任何需要解决方案的人,我能够通过使用 TokenValidatedContext
在 Startup.cs
中添加租户 ID 作为新声明来解决此问题(因为我在 TokenValidatedContext
在那一刻)。看起来像这样:
ctx.HttpContext.User.Identity?.AddClaim(New Claim('tenant'));
稍后在 Tenant Provider 中我可以访问此声明。