mar*_*onx 9 asp.net-identity asp.net-core-2.0
我有一个工作的Asp.Net Core应用程序,默认身份处理.现在我想将它用于多域.我用DomainId扩展了ApplicationUser.我如何处理用户名/电子邮件以验证/注册用户,以及当前的DomainId?
当用户注册,登录系统时,获取当前的DomainId并不是问题,我有一个有效的多租户Asp.Net Core系统.我只对使用DomainId的用户管理有问题.
这有什么设置吗?为了获得这种功能,我应该覆盖什么?例如UserStore,UserManager?
我找到了一些旧的Asp.Net Identity教程,例如:https://www.scottbrady91.com/ASPNET-Identity/Quick-and-Easy-ASPNET-Identity-Multitenancy 但我找不到任何新的教程Asp.Net核心身份.
mar*_*onx 14
最后我明白了.首先,我必须将用户电子邮件设置为不唯一.旁注:我也在使用UserName的电子邮件,我不想向用户询问UserName:
services.Configure<IdentityOptions>(options =>
{
options.User.RequireUniqueEmail = false;
});
Run Code Online (Sandbox Code Playgroud)
当一个新用户注册自己时,我正在将当前的域ID合并到UserName,这有助于用户通过完全不同的域向系统注册相同的Email/UserName.
然后我必须创建我的自定义UserManager,我在那里覆盖FindByEmail:
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MultiShop.Core.Repositories.User;
using MultiShop.Core.Tenant;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Test
{
public class MyShopUserManager<TUser> : UserManager<TUser>, IDisposable where TUser : class
{
private readonly ITenantService tenantService;
private readonly IUserRepository userRepository;
public MyUserManager(IUserStore<TUser> store, IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<TUser> passwordHasher, IEnumerable<IUserValidator<TUser>> userValidators,
IEnumerable<IPasswordValidator<TUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<TUser>> logger,
ITenantService tenantService, IUserRepository userRepository)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
this.tenantService = tenantService;
this.userRepository = userRepository;
}
public override async Task<TUser> FindByEmailAsync(string email)
{
ThrowIfDisposed();
if (email == null)
{
throw new ArgumentNullException(nameof(email));
}
var users = (await userRepository.GetAllAsync()).Where(u => u.Email == email);
if (users == null)
{
return null;
}
if (users.Count() == 1)
{
return await Store.FindByIdAsync(users.First().Id.ToString(), CancellationToken);
}
var currentDomain = tenantService.GetCurrentDomainAsync().Result;
var user = users.SingleOrDefault(u => u.DomainId == currentDomain.Id);
if (user == null)
{
return null;
}
return await Store.FindByIdAsync(user.Id.ToString(), CancellationToken);
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,由于多域和生成的UserNames,您应该使用userManager.FindByEmailAsync,而不是FindByNameAsync.
我必须创建自定义SignInManager来处理多域用户:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MultiShop.Core.Tenant;
using MultiShop.Data.Entities;
using System.Threading.Tasks;
namespace Test
{
public class MySignInManager : SignInManager<ApplicationUser>
{
private readonly ITenantService tenantService;
public MySignInManager(UserManager<ApplicationUser> userManager, IHttpContextAccessor contextAccessor,
IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor,
ILogger<SignInManager<ApplicationUser>> logger, IAuthenticationSchemeProvider schemes,
ITenantService tenantService)
: base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes)
{
this.tenantService = tenantService;
}
public override async Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure)
{
var currentDomain = await tenantService.GetCurrentDomainAsync();
return await base.PasswordSignInAsync($"{userName}{currentDomain.Id}", password, isPersistent, lockoutOnFailure);
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后,我必须将我的自定义管理器注册到Asp.Net Core Identity DI:
services
.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<MultiShopDbContext>()
.AddDefaultTokenProviders()
//my custom managers for domain segmented users
.AddUserManager<MyUserManager<ApplicationUser>>()
.AddSignInManager<MySignInManager>();
Run Code Online (Sandbox Code Playgroud)
而已!
| 归档时间: |
|
| 查看次数: |
4136 次 |
| 最近记录: |