Asp.net web api2 使用Identity框架实现多租户的简单方法。如何?

Asp.net web api2 使用Identity框架实现多租户的简单方法。如何?,asp.net-web-api2,asp.net-identity,asp.net-identity-2,asp.net-identity-3,Asp.net Web Api2,Asp.net Identity,Asp.net Identity 2,Asp.net Identity 3,我想在使用身份验证框架的web api应用程序中支持多租户。我计划拥有一个单一站点和一个数据库,其中多个租户拥有多个用户。我很乐意在用户名前面加上租户id,以便登录,然后在将其返回到客户端应用程序时将其删除。 但是,我不确定如何“拦截”用户登录。也就是说,在将用户名传递到框架进行身份验证之前,我将在何处实现使用租户ID作为用户名前缀。 有人能告诉我如何处理上述问题吗。一个小例子和指向在线文档的指针将被告知 谢谢。Scott Brady提供了一个解决方案,您可以在这里阅读解释,我只需在这里编写代码

我想在使用身份验证框架的web api应用程序中支持多租户。我计划拥有一个单一站点和一个数据库,其中多个租户拥有多个用户。我很乐意在用户名前面加上租户id,以便登录,然后在将其返回到客户端应用程序时将其删除。
但是,我不确定如何“拦截”用户登录。也就是说,在将用户名传递到框架进行身份验证之前,我将在何处实现使用租户ID作为用户名前缀。
有人能告诉我如何处理上述问题吗。一个小例子和指向在线文档的指针将被告知

谢谢。

Scott Brady提供了一个解决方案,您可以在这里阅读解释,我只需在这里编写代码并进行一些更新

解决方案

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

公共类应用程序用户: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);
       }
}
然后,您可以为每个租户创建seprate用户管理器,如下所示:

用户1

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;
        }
    }
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;
        }
    }

tenantId可以是每个注册租户的Id。

感谢您提供的示例。然而,在SaaS环境中,我不知道如何为每个租户动态创建一个单独的UserManager——也就是说,当一个新租户注册时。您只需要创建UserManager,并将tenantId动态传递给userStore查看我的UpdateAnks以获得更新。然而,回到我最初的问题,我如何/在哪里“截取”用户名和/或租户id?我可能错过了一些明显的东西。当用户登录框架时,使用IdentityFactoryOptions和IOwinContext调用my ApplicationUserManager的静态Create()方法。这是我应该设置租户id的地方(例如,从用户名中提取)。但是,我不确定如何获取用户名。
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));