【发布时间】:2020-12-12 03:28:47
【问题描述】:
我有一个 .NET 5 ASP.NET Core API,我正在尝试使用 Autofac.AspNetCore.Multitenant v4.0.1 设置多租户。我已经实现了一个 TenantIdentificationStrategy,它从当前用户主体的声明中识别租户。 问题在于,在 Autofac 解析租户标识符时,用户似乎尚未填充。
此处的 Autofac 文档 https://autofaccn.readthedocs.io/en/latest/advanced/multitenant.html#tenant-identification 状态:
ITenantIdentificationStrategy 允许您检索租户 适合您的应用程序的任何位置的 ID:环境 变量,当前用户主体上的角色,传入请求 价值,或其他任何地方。
由于这个声明,我认为这应该有效,所以我想知道我是否做错了什么,或者框架是否存在错误,或者文档是否说明了一些不受框架。
知道如何让它发挥作用吗?
在我的应用配置下方找到:
计划
private static IHostBuilder CreateHostBuilder(string[] args)
=> Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacMultitenantServiceProviderFactory(Startup.ConfigureMultitenantContainer))
.ConfigureWebHostDefaults(webHostBuilder =>
{
webHostBuilder.UseStartup<Startup>();
});
启动
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
// [...]
});
services.AddControllers();
services.AddAutofacMultitenantRequestServices();
}
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<ClaimTenantIdentificationStrategy>()
.As<ITenantIdentificationStrategy>()
.SingleInstance();
builder.RegisterType<SomeService>()
.As<ISomeService>()
.InstancePerTenant();
}
public static MultitenantContainer ConfigureMultitenantContainer(IContainer container)
=> new MultitenantContainer(container.Resolve<ITenantIdentificationStrategy>(), container);
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
TenantIdentificationStrategy 实施
public class ClaimTenantIdentificationStrategy : ITenantIdentificationStrategy
{
private readonly IHttpContextAccessor _httpContextAccessor;
public ClaimTenantIdentificationStrategy(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}
public bool TryIdentifyTenant(out object tenantId)
{
tenantId = null;
var claimsPrincipal = _httpContextAccessor.HttpContext?.User;
var claimsIdentity = claimsPrincipal?.Identity;
if (claimsIdentity != null && claimsIdentity.IsAuthenticated)
{
var identifier = claimsPrincipal.FindFirst("tenantId")?.Value;
if (!string.IsNullOrEmpty(identifier))
tenantId = identifier;
}
return tenantId != null;
}
}
编辑:TenantIdentificationStrategy
public class ClaimTenantIdentificationStrategy : ITenantIdentificationStrategy
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ITenantStore _tenantStore;
public ClaimTenantIdentificationStrategy(IHttpContextAccessor httpContextAccessor, ITenantStore tenantStore)
{
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
_tenantStore = tenantStore ?? throw new ArgumentNullException(nameof(tenantStore));
}
public bool TryIdentifyTenant(out object tenantId)
{
var httpContext = _httpContextAccessor.HttpContext;
tenantId = httpContext?.Items["TenantId"];
if (tenantId != null)
return true;
var authorizationHeaderValue = httpContext?.Request?.Headers?[HeaderNames.Authorization];
if (authorizationHeaderValue.HasValue && !StringValues.IsNullOrEmpty(authorizationHeaderValue.Value))
{
var authorizationHeader = AuthenticationHeaderValue.Parse(authorizationHeaderValue);
var jwtTokenHandler = new JwtSecurityTokenHandler();
var jwtToken = jwtTokenHandler.ReadJwtToken(authorizationHeader.Parameter);
var tenantIdClaim = jwtToken.Claims
.FirstOrDefault(x => x.Type == "tenantId");
if (tenantIdClaim != null && _tenantStore.IsValidTenant(tenantIdClaim.Value))
{
tenantId = tenantIdClaim.Value;
httpContext.Items["TenantId"] = tenantId;
return true;
}
}
return false;
}
}
【问题讨论】:
标签: asp.net-core asp.net-core-webapi autofac multi-tenant