gpt4 book ai didi

c# - IdenityServer 和每个租户策略实现数据库

转载 作者:行者123 更新时间:2023-12-04 00:54:41 25 4
gpt4 key购买 nike

我正在尝试实现 Multi-Tenancy IdentityServer,每个租户都有自己的数据库。

客户端我正在使用 Angular,我正在使用 oidc-client 传递我的 tenantId,如下所示:

角度

import { UserManager, UserManagerSettings, User } from "oidc-client";

private manager = new UserManager(getClientSettings());

login() {
return this.manager.signinRedirect({
extraQueryParams: {
tenant: AppConfig.settings.connectionApiData.tenant,
},
});
}

AppIdentityDbContext

public class AppIdentityDbContext : IdentityDbContext<AppUser>
{
private readonly IApplicationService _applicationService;
private readonly HttpContext _httpContext;
private readonly ITenantProvider provider;
private readonly Tenant.Tenant _tenant;

public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options,
ITenantProvider provider,
IHttpContextAccessor httpContextAccessor, IApplicationService applicationService) : base(options)
{
_tenant = provider.GetTenantById(_applicationService.TenantId);
_httpContext = httpContextAccessor.HttpContext;
_applicationService = applicationService;
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);

modelBuilder.Entity<IdentityRole>().HasData(new IdentityRole
{Name = Constants.Roles.Consumer, NormalizedName = Constants.Roles.Consumer.ToUpper()});
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{

optionsBuilder.UseMySql(_tenant.DatabaseConnectionString);
base.OnConfiguring(optionsBuilder);
}
}

租户提供者

 public class Tenant
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Host { get; set; }
public string DatabaseConnectionString { get; set; }
}

public interface ITenantProvider
{
Tenant GetFirstTenant();
Tenant GetTenantById(Guid id);
}

public class TenantProvider : ITenantProvider
{
private static readonly IList<Tenant> Tenants = new List<Tenant>
{
new Tenant
{
Id = Guid.Parse("51aab199-1482-4f0d-8ff1-5ca0e7bc525a"),
Name = "Imaginary corp",
DatabaseConnectionString = "server=localhost;port=3306;database=AuthServer;user=root;password=root"
},

new Tenant
{
Id = Guid.Parse("ae4e21fa-57cb-4733-b971-fdd14c4c667e"),
Name = "The Very Big corp",
DatabaseConnectionString = "server=localhost;port=3306;database=AuthServer;user=root;password=root"
}
};


public Tenant GetFirstTenant()
{
return Tenants.First();
}

public Tenant GetTenantById(Guid id)
{
return Tenants.FirstOrDefault(t => t.Id == id);
}
}

Startup.cs 中为了添加 AddIdentity 我添加了一个连接字符串,但连接字符串必须来自 TenantProvider

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppIdentityDbContext>(
options => options.UseMySql(Configuration.GetConnectionString("DefaultConnection")
));

services.AddIdentity<AppUser, IdentityRole>()
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();

services.AddIdentityServer()
.AddDeveloperSigningCredential()
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder => builder.UseMySql(Configuration.GetConnectionString("DefaultConnection"));

// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30; // interval in seconds
})
//.AddInMemoryPersistedGrants()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddAspNetIdentity<AppUser>();

services.AddTransient<IProfileService, IdentityClaimsProfileService>();

services.AddScoped<IApplicationService, ApplicationService>();

services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()));

services.AddMvc(options =>
{
options.EnableEndpointRouting = false;
}).SetCompatibilityVersion(CompatibilityVersion.Latest);


services.AddTransient<ITenantProvider, TenantProvider>();
}



TenantMiddleware 在 applicationService 中设置 tenantId,以便稍后通过 tenantProvider 注入(inject)它

租户中间件

public class TenantMiddleware
{
private readonly RequestDelegate next;

public TenantMiddleware(RequestDelegate next)
{
this.next = next;
}

public async Task Invoke(HttpContext context, IApplicationService applicationService, ITenantProvider tenant)
{
var queryString = HttpUtility.ParseQueryString(context.Request.Query["ReturnUrl"]);

Guid.TryParse(queryString["tenant"], out var tenantId);

applicationService.TenantId = tenantId;
await next(context);
}
}

如果我必须先等待请求由 TenantMiddleware 处理,我该如何在 Startup.cs 中设置 AppIdentityDbContext?会成功吗?

最佳答案

对于具有不同数据库源的 Multi-Tenancy ,不可能在 Startup.cs 上设置它,它必须在运行时创建一些 ContextFactory 和其他东西来处理 DbContext 设置。您可以尝试这篇文章,它可能会提示您正在寻找的解决方案,Building Multi-tenant Web API With .NET Core and Best Practices .

关于c# - IdenityServer 和每个租户策略实现数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63474310/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com