我有一个多租户.NET Core Web应用程序,其中当前用户的租户通过中间件解决。特别是,租户通过名为SaasKit.Multitenancy的库进行解析。
要使用此库,请将此行放入ConfigureServices()
:
public IServiceProvider ConfigureServices(IServiceCollection services) { // (omitted for brevity) // The 'Tenant' type is what you resolve to, using 'ApplicationTenantResolver' services.AddMultitenancy<Tenant, ApplicationTenantResolver>(); // ... }
并且您将此行放入
Configure()
以将其添加到中间件管道中:
public void Configure(IApplicationBuilder app) { // ... app.UseAuthentication(); app.UseMultitenancy<Tenant>(); //this line app.UseMvc(ConfigureRoutes); // ... }
这将导致在中间件中执行以下方法,该方法可解决当前用户的租户:
public async Task<TenantContext<Tenant>> ResolveAsync(HttpContext context) { //whatever you need to do to figure out the tenant goes here. }
这允许将此方法的结果(无论解决租户的情况如何)注入到所需的任何类中,如下所示:
private readonly Tenant _tenant; public HomeController(Tenant tenant) { _tenant = tenant; }
到目前为止,我们一直在使用.NET Identity平台对用户进行身份验证,将用户数据存储在应用程序的数据库中。但是,我们的新租户希望能够通过SSO对用户进行身份验证。
我已经了解了大多数SSO内容-我正在使用Azure AD登录用户,然后单击my organization's Azure AD tenant will be able to federate with their Identity Provider。简而言之,此代码在ConfigureServices
中添加了Identity和AzureAD身份验证:
public IServiceProvider ConfigureServices(IServiceCollection services) { // rest of the code is omitted for brevity services.AddIdentity<ApplicationUser, ApplicationRole>(config => { config.User.RequireUniqueEmail = true; config.Password.RequiredLength = 12; }).AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders(); services.AddAuthentication(AzureADDefaults.AuthenticationScheme) .AddAzureAD(options => _configuration.Bind("AzureAd", options)).AddCookie(); // policy gets user past [Authorize] if they are signed in with Identity OR Azure AD services.AddMvc(options => { var policy = new AuthorizationPolicyBuilder( AzureADDefaults.AuthenticationScheme, IdentityConstants.ApplicationScheme ).RequireAuthenticatedUser() .Build(); options.Filters.Add(new AuthorizeFilter(policy)); }); }
使用身份时,我已经能够通过UserManager解决用户的租户,如下所示:
public async Task<TenantContext<Tenant>> ResolveAsync(HttpContext context) { TenantContext<Tenant> tenantContext = new TenantContext<Tenant>(new ApplicationTenant()); if (context.User.Identity.IsAuthenticated) { var user = await _userManager.Users .Include(x => x.Tenant) .FirstOrDefaultAsync(x => x.UserName == email); if (user?.Tenant != null) { tenantContext = new TenantContext<Tenant>(user.Tenant); _logger.LogDebug("The current tenant is " + user.Tenant.Name); return await Task.FromResult(tenantContext); } } return await Task.FromResult(tenantContext); }
我的计划是修改此代码,以便获取当前用户的声明,该声明可用于推断用户属于哪个租户。 但是,尽管通过用户登录,通过Azure AD对用户进行身份验证时,
HttpContext.User
在中间件中始终为空。它不为null,但HttpContext.User.Identity.IsAuthenticated
始终为false且HttpContext.User.Claims
为空。路由完成并且代码到达控制器后,我才看到填充的HttpContext.User
值。
我已经尝试了几乎所有可行的方式来重组中间件,但无济于事。让我感到困惑的是,当用Identity验证用户身份时,在租户解析器中填充了HttpContext.User
。考虑到这一点,我不确定通过Azure AD进行身份验证时如何在中间件中访问用户的声明。
我能想到的最好的解决方案是,通过调用通过索偿解决租户的方法来修改当前租户注入代码的每个实例。如果租户在受[Authorize]属性限制的区域中为null,则意味着该用户通过Azure AD登录,这使我可以查看他们的声明。但是,我无法在中间件中访问用户的声明,这让我感到困扰,因为我不确定这里到底发生了什么。
我有一个多租户.NET Core Web应用程序,其中当前用户的租户通过中间件解决。特别是,租户可以通过名为SaasKit.Multitenancy的库进行解析。要使用此库,...
由于您正尝试从自定义组件访问HttpContext,因此需要将HttpContextAccessor
添加到服务集合中,如下所示:
我怀疑您可能正在.NET Core 2.0上运行并运行到此issue。