【问题标题】:Logged user based connection string in .NET Core在 .NET Core 中记录基于用户的连接字符串
【发布时间】:2018-11-15 15:47:50
【问题描述】:

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

每个客户还有一个单独的数据库及其数据,其连接字符串存储在身份数据库的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。

【问题讨论】:

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


    【解决方案1】:

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

    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 Console 中运行 Update-Database 命令。现在您有了 Customer 表,并且在 AspNetUsers 表中有 CustomerConnectionString 列。

    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. 添加Identity服务后,在你的应用启动类中注册你刚刚创建的自定义工厂:

      // 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. 修改创建/编辑用户视图/控制器,在视图上添加客户下拉列表,在AccountController中的Register函数中获取自定义id,从db中查询custom的connectingString,并保存在ApplicationUser对象中:

       var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
       var result = await _userManager.CreateAsync(user, model.Password);
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-02
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      • 2018-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多