.NET Core中记录的基于用户的连接字符串

时间:2018-11-14 10:31:59

标签: .net-core asp.net-identity multi-tenant dbcontext asp.net-core-1.1

我有一个使用身份数据库存储用户和客户的应用程序。

每个客户都有一个单独的数据库,其中包含其数据,其连接字符串存储在身份数据库的Customer表中。

AspNetUsers有一个字段来告诉用户该用户属于哪个客户(身份数据库)。

我想在用户登录时为他分配连接字符串,并在会话期间使其在应用程序中可用。

我目前有客户模型:

public partial class `Customer`
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int NoLicenses { get; set; }
    public bool? Enabled { get; set; }
    public string CustomerConnectionString { get; set; }
}

和用户模型:

public class ApplicationUser : IdentityUser
{
    public string CustomerId { get; set; }

    public bool? IsEnabled { get; set; }

    // there ideally I'd have a connstring property
}

模型映射数据库表字段。

我正在使用.NET Core 1.1和EF Core。

1 个答案:

答案 0 :(得分:0)

使用默认的ASP.NET Identity模板,您可以:

  1. 扩展Models文件夹中的ApplicationUser类:

    public class ApplicationUser : IdentityUser
    {
        public string CustomerId { get; set; }
    
        public bool? IsEnabled { get; set; }
    
        //add your custom claims
        public string CustomerConnectionString { get; set; }
    }
    
  2. 将自定义模型添加到“数据”文件夹中的ApplicationDbContext

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            // 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);
    
    
        }
    
        public DbSet<Customer> Customers { get; set; }
    }
    
  3. 同步数据库:Add-Migration xxxx,然后在Package Manager控制台中运行Update-Database命令。现在您有了Customer表,并且在CustomerConnectionString表中有AspNetUsers列。

  4. 通过继承默认实例来创建IUserClaimsPrincipalFactory的自己的实现,以从您的用户生成ClaimsPrincipal:

    public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>
    {
        public AppClaimsPrincipalFactory(
          UserManager<ApplicationUser> userManager
          , RoleManager<IdentityRole> roleManager
          , IOptions<IdentityOptions> optionsAccessor)
        : base(userManager, roleManager, optionsAccessor)
        { }
    
        public async override Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
        {
            var principal = await base.CreateAsync(user);
    
            if (!string.IsNullOrWhiteSpace(user.CustomerId))
            {
    
                ((ClaimsIdentity)principal.Identity).AddClaims(new[] {
                new Claim("customid", user.CustomerId)
                });
            }
    
            if (!string.IsNullOrWhiteSpace(user.CustomerConnectionString))
            {
    
                ((ClaimsIdentity)principal.Identity).AddClaims(new[] {
                new Claim("CustomerConnectionString", user.CustomerConnectionString)
                });
            }
            return principal;
        }
    }
    
  5. 添加身份服务后,在应用程序启动类中注册刚创建的自定义工厂:

    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    
    services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
    
      services.AddScoped<Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory<ApplicationUser>, AppClaimsPrincipalFactory>();
    
  6. 然后您可以访问以下声明:

    var connectString = User.Claims.FirstOrDefault(c => c.Type == "CustomerConnectionString").Value;
    
  7. 修改创建/编辑用户视图/控制器,在视图上添加客户下拉列表,在Register的{​​{1}}函数中获取自定义ID,从db中查询custom的connectingString,并保存在AccountController对象中:

    ApplicationUser