Asp.net web api2 使用Identity框架实现多租户的简单方法。如何?
我想在使用身份验证框架的web api应用程序中支持多租户。我计划拥有一个单一站点和一个数据库,其中多个租户拥有多个用户。我很乐意在用户名前面加上租户id,以便登录,然后在将其返回到客户端应用程序时将其删除。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提供了一个解决方案,您可以在这里阅读解释,我只需在这里编写代码
但是,我不确定如何“拦截”用户登录。也就是说,在将用户名传递到框架进行身份验证之前,我将在何处实现使用租户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));