每个租户的唯一用户名和电子邮件
Unique UserName & Email per tenant
我正在使用 ASP.NET Core 2.1
编写一个多租户应用程序。
我想覆盖默认的用户创建相关验证机制。
目前我无法创建多个具有相同 UserName
的用户。
我的 ApplicationUser
模型有一个名为 TenantID
的字段。
我想要实现的目标:UserName
& EmailAddress
每个租户必须是唯一的。
我一直在谷歌搜索解决方案,但没有找到关于 asp.net core
的太多信息。
大多数结果只会涵盖 Entity Framework
个方面,就好像 overriding OnModelCreating(...)
method. 的问题与 ASP.NET 身份的非核心版本有关。
我想知道我是否应该继续研究 OnModelCreating
方法?
或者,也许 Identity
周围还需要覆盖其他内容?
首先,您需要禁用身份的内置验证机制:
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
// disable the built-in validation
options.User.RequireUniqueEmail = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
然后,假设您要使用 ASP.NET Core with Identity 模板注册用户,您可以这样做:
[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 = await 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
时,将在创建用户之前进行验证。
我正在使用 ASP.NET Core 2.1
编写一个多租户应用程序。
我想覆盖默认的用户创建相关验证机制。
目前我无法创建多个具有相同 UserName
的用户。
我的 ApplicationUser
模型有一个名为 TenantID
的字段。
我想要实现的目标:UserName
& EmailAddress
每个租户必须是唯一的。
我一直在谷歌搜索解决方案,但没有找到关于 asp.net core
的太多信息。
大多数结果只会涵盖 Entity Framework
个方面,就好像 overriding OnModelCreating(...)
method.
我想知道我是否应该继续研究 OnModelCreating
方法?
或者,也许 Identity
周围还需要覆盖其他内容?
首先,您需要禁用身份的内置验证机制:
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
// disable the built-in validation
options.User.RequireUniqueEmail = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
然后,假设您要使用 ASP.NET Core with Identity 模板注册用户,您可以这样做:
[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 = await 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
时,将在创建用户之前进行验证。