每个租户的唯一用户名和电子邮件

问题描述 投票:3回答:1

我正在使用ASP.NET Core 2.1编写一个多租户应用程序。

我想覆盖默认的用户创建相关的验证机制。

目前我无法使用相同的UserName创建多个用户。

我的ApplicationUser模型有一个叫做TenantID的领域。

我想要实现的目标:UserNameEmailAddress必须是每个租户独一无二的。

我一直在谷歌搜索解决方案,但没有找到asp.net core在这一个上的太多信息。

大多数结果只会涵盖Entity Framework方面,好像这只是overriding OnModelCreating(...)方法的问题。 Some与ASP.NET身份的非核心版本有关。

我想知道我是否应该继续调查OnModelCreating方法?

或许,还有其他需要在Identity周围被覆盖的东西?

c# asp.net-core multi-tenant asp.net-core-identity
1个回答
4
投票

首先,您需要禁用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时,验证将在创建用户之前进行。

© www.soinside.com 2019 - 2024. All rights reserved.