具有身份框架的多租户的简单方法.如何



我想支持使用身份框架进行身份验证的Web API应用中的多租赁。我计划拥有一个单个站点和一个具有多个用户的租户的单个数据库。我很高兴将用户名带有租户ID以登录用途,然后在将其返回客户端应用程序时将其剥离。
但是,我不确定如何"拦截"用户登录。也就是说,我在哪里可以在之前使用租户ID 实现前缀的用户名。
有人可以让我知道如何处理以上内容。一个很小的例子和在线文档的指示将得到认可。

谢谢。

这是斯科特·布雷迪(Scott Brady)的解决方案,您可以在这里阅读说明我只是在这里写代码。

解决方案

向您的用户添加新属性以确定租户。

public class ApplicationUser : IdentityUser { public int TenantId { get; set; } }

然后,您需要自定义UserStore以使其意识到您的新用户属性。

 public class ApplicationUserStore<TUser> : UserStore<TUser> 
   where TUser : ApplicationUser {
      public ApplicationUserStore(DbContext context, int tenantId)
        : base(context) {
              TenantId = tenantId
      }
      public int TenantId { get; set; }

      public override Task CreateAsync(TUser user) {
          if (user == null) {
              throw new ArgumentNullException("user");
          }
          user.TenantId = this.TenantId;
          return base.CreateAsync(user);
      }
      public override Task<TUser> FindByEmailAsync(string email) {
          return this.GetUserAggregateAsync(u => u.Email.ToUpper() == email.ToUpper() 
             && u.TenantId == this.TenantId);
      }
       public override Task<TUser> FindByNameAsync(string userName) {
           return this.GetUserAggregateAsync(u => u.UserName.ToUpper() ==                                 userName.ToUpper() 
             && u.TenantId == this.TenantId);
       }

       public override Task<IdnUser> FindByIdAsync(long userId)
       {
           return this.GetUserAggregateAsync(u => u.Id == userId && u.TenantId == this.tenantId);
       }
}

,您还需要自定义IdentityDbContext以支持多端。

public class ApplicationUserDbContext<TUser> : IdentityDbContext<TUser> 
  where TUser : ApplicationUser {
    public ApplicationUserDbContext(string nameOrConnectionString)
      : base(nameOrConnectionString) {
    }
    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        base.OnModelCreating(modelBuilder);
        var user = modelBuilder.Entity<TUser>();
        user.Property(u => u.UserName)
            .IsRequired()
            .HasMaxLength(256)
            .HasColumnAnnotation("Index", new IndexAnnotation(
                new IndexAttribute("UserNameIndex") { IsUnique = true, Order = 1}));
        user.Property(u => u.TenantId)
            .IsRequired()
            .HasColumnAnnotation("Index", new IndexAnnotation(
                new IndexAttribute("UserNameIndex") { IsUnique = true, Order = 2 }));
    }

   protected override DbEntityValidationResult ValidateEntity(
    DbEntityEntry entityEntry, IDictionary<object, object> items) {
      if (entityEntry != null && entityEntry.State == EntityState.Added) {
        var errors = new List<DbValidationError>();
        var user = entityEntry.Entity as TUser;
        if (user != null) {
            if (this.Users.Any(u => string.Equals(u.UserName, user.UserName) 
              && u.TenantId == user.TenantId)) {
                errors.Add(new DbValidationError("User", 
                  string.Format("Username {0} is already taken for AppId {1}", 
                    user.UserName, user.TenantId)));
            }
            if (this.RequireUniqueEmail 
              && this.Users.Any(u => string.Equals(u.Email, user.Email) 
              && u.TenantId == user.TenantId)) {
                errors.Add(new DbValidationError("User", 
                  string.Format("Email Address {0} is already taken for AppId {1}", 
                    user.UserName, user.TenantId)));
            }
        }
        else {
            var role = entityEntry.Entity as IdentityRole;
            if (role != null && this.Roles.Any(r => string.Equals(r.Name, role.Name))) {
                errors.Add(new DbValidationError("Role", 
                  string.Format("Role {0} already exists", role.Name)));
            }
        }
        if (errors.Any()) {
            return new DbEntityValidationResult(entityEntry, errors);
        }
    }
    return new DbEntityValidationResult(entityEntry, new List<DbValidationError>());
    }
}

然后您可以为每个租户创建Seprate用户经理:

user1

public class AppCustomerManager : UserManager<ApplicationUser>
    {
        public AppCustomerManager(IUserStore<ApplicationUser> store)
            : base(store)
        {
            UserTokenProvider = new PhoneNumberTokenProvider<ApplicationUser >();
        }
        public static AppCustomerManager Create(IdentityFactoryOptions<AppCustomerManager> options, IOwinContext context)
        {
            var appDbContext = context.Get<ApplicationUserDbContext>();
            //here you define your tenant by passing an int to userstore
            var appUserManager = new AppCustomerManager(new ApplicationUserStore(appDbContext, 1));
            var dataProtectionProvider = options.DataProtectionProvider;
            if (dataProtectionProvider != null)
            {
                appUserManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"))
                {
                    TokenLifespan = TimeSpan.FromHours(6)
                };
            }

            return appUserManager;
        }
    }

用户2

public class AppDeliveryManager : UserManager<ApplicationUser>
    {
        public AppDeliveryManager(IUserStore<ApplicationUser> store)
            : base(store)
        {
            UserTokenProvider = new PhoneNumberTokenProvider<ApplicationUser >();
        }
        public static AppDeliveryManager Create(IdentityFactoryOptions<AppDeliveryManager> options, IOwinContext context)
        {
            var appDbContext = context.Get<IdnDbContext>();
            //here you define your tenant by passing an int to userstore
            var appUserManager = new AppDeliveryManager(new ApplicationUserStore(appDbContext, 2));
            var dataProtectionProvider = options.DataProtectionProvider;
            if (dataProtectionProvider != null)
            {
                appUserManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"))
                {
                    TokenLifespan = TimeSpan.FromHours(6)
                };
            }
            return appUserManager;
        }
    }

更新:

 var appUserManager = new AppDeliveryManager(new ApplicationUserStore(appDbContext, tenantId));

和tenantid可以是注册的每个租户的ID。

相关内容

  • 没有找到相关文章

最新更新