我正在使用ASP.NET Core 2.1
对多租户应用进行编码。
我想覆盖与用户创建相关的默认验证机制。
当前,我无法使用相同的UserName
创建多个用户。
我的ApplicationUser
模型有一个名为TenantID
的字段。
我要实现的目标:UserName
和EmailAddress
每个租户必须唯一。
我一直在寻找一种解决方案,但是没有找到关于asp.net core
的更多信息。
大多数结果仅涉及Entity Framework
个方面,就好像这只是overriding OnModelCreating(...)
方法的问题一样。 Some与ASP.NET Identity的非核心版本有关。
我想知道我是否应该继续研究OnModelCreating
方法?
也许,Identity
周围还有其他需要重写的东西吗?
答案 0 :(得分:4)
首先,您需要禁用身份的内置验证机制:
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
// disable the built-in validation
options.User.RequireUniqueEmail = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
然后,假设您正在使用带有身份模板的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
时,验证将在创建用户之前进行。