我正在使用ASP.NET Core 2.1
编写一个多租户应用程序。
我想覆盖默认的用户创建相关的验证机制。
目前我无法使用相同的UserName
创建多个用户。
我的ApplicationUser
模型有一个叫做TenantID
的领域。
我想要实现的目标:UserName
和EmailAddress
必须是每个租户独一无二的。
我一直在谷歌搜索解决方案,但没有找到asp.net core
在这一个上的太多信息。
大多数结果只会涵盖Entity Framework
方面,好像这只是overriding OnModelCreating(...)
方法的问题。 Some与ASP.NET身份的非核心版本有关。
我想知道我是否应该继续调查OnModelCreating
方法?
或许,还有其他需要在Identity
周围被覆盖的东西?
首先,您需要禁用Identity的内置验证机制:
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
// disable the built-in validation
options.User.RequireUniqueEmail = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
然后,假设您使用带有Identity模板的ASP.NET Core注册用户,您可以这样做:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
return View(model);
}
// check for duplicates
bool combinationExists = await _context.Users
.AnyAsync(x => x.UserName == model.UserName
&& x.Email == model.Email
&& x.TenantId == model.TenantId);
if (combinationExists)
{
return View(model);
}
// create the user otherwise
}
如果你不想在控制器中进行那种检查而宁愿保留身份流,你也可以简单地创建自己的IUserValidator<ApplicationUser>
:
public class MultiTenantValidator : IUserValidator<ApplicationUser>
{
public async Task<IdentityResult> ValidateAsync(UserManager<ApplicationUser> manager, ApplicationUser user)
{
bool combinationExists = manager.Users
.AnyAsync(x => x.UserName == user.UserName
&& x.Email == user.Email
&& x.TenantId == user.TenantId);
if (combinationExists)
{
return IdentityResult.Failed(new IdentityResult { Description = "The specified username and email are already registered in the given tentant" });
}
// here the default validator validates the username for valid characters,
// let's just say all is good for now
return IdentityResult.Success;
}
}
然后你会告诉Identity使用你的验证器:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddUserValidator<MultiTenantValidator>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
有了这个,当你调用UserManager.CreateAsync
时,验证将在创建用户之前进行。