Validation 重写.NET Core Identity 2.1的UserValidator.cs中的ValidateAsync
我正在自定义用户名验证,以允许使用相同的用户名(非唯一)。这是一个附加字段“已删除”,作为对身份用户的软删除。因此,定制涉及更改当前验证以检查用户名是否已存在,并且删除的用户名是否为false以仅触发DuplicateUserName错误 我所做的是创建一个CustomUserValidator类,并重写UserValidator.cs中的ValidateAsync方法以及ValidateUserName方法。代码如下: CustomUserValidator.csValidation 重写.NET Core Identity 2.1的UserValidator.cs中的ValidateAsync,validation,asp.net-core-mvc,asp.net-identity,Validation,Asp.net Core Mvc,Asp.net Identity,我正在自定义用户名验证,以允许使用相同的用户名(非唯一)。这是一个附加字段“已删除”,作为对身份用户的软删除。因此,定制涉及更改当前验证以检查用户名是否已存在,并且删除的用户名是否为false以仅触发DuplicateUserName错误 我所做的是创建一个CustomUserValidator类,并重写UserValidator.cs中的ValidateAsync方法以及ValidateUserName方法。代码如下: CustomUserValidator.cs public class C
public class CustomUserValidator<TUser> : UserValidator<TUser>
where TUser : ApplicationUser
{
public override async Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user)
{
if (manager == null)
{
throw new ArgumentNullException(nameof(manager));
}
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
var errors = new List<IdentityError>();
await ValidateUserName(manager, user, errors);
if (manager.Options.User.RequireUniqueEmail)
{
await ValidateEmail(manager, user, errors);
}
return errors.Count > 0 ? IdentityResult.Failed(errors.ToArray()) : IdentityResult.Success;
}
private async Task ValidateUserName(UserManager<TUser> manager, TUser user, ICollection<IdentityError> errors)
{
var userName = await manager.GetUserNameAsync(user);
if (string.IsNullOrWhiteSpace(userName))
{
errors.Add(Describer.InvalidUserName(userName));
}
else if (!string.IsNullOrEmpty(manager.Options.User.AllowedUserNameCharacters) &&
userName.Any(c => !manager.Options.User.AllowedUserNameCharacters.Contains(c)))
{
errors.Add(Describer.InvalidUserName(userName));
}
else
{
//var owner = await manager.FindByNameAsync(userName);
var owner = manager.Users.Where(x => !x.Deleted &&
x.UserName.ToUpper() == userName.ToUpper())
.FirstOrDefault();
if (owner != null &&
!string.Equals(await manager.GetUserIdAsync(owner), await manager.GetUserIdAsync(user)))
{
errors.Add(Describer.DuplicateUserName(userName));
}
}
}
}
公共类CustomUserValidator:UserValidator
其中TUser:ApplicationUser
{
公共覆盖异步任务ValidateAsync(UserManager,TUser用户)
{
if(manager==null)
{
抛出新的ArgumentNullException(nameof(manager));
}
if(user==null)
{
抛出新ArgumentNullException(nameof(user));
}
var errors=新列表();
等待ValidateUserName(经理、用户、错误);
if(manager.Options.User.RequireUniqueEmail)
{
等待ValidateEmail(经理、用户、错误);
}
返回errors.Count>0?IdentityResult.Failed(errors.ToArray()):IdentityResult.Success;
}
专用异步任务ValidateUserName(UserManager管理器、TUser用户、ICollection错误)
{
var userName=await manager.GetUserNameAsync(用户);
if(string.IsNullOrWhiteSpace(用户名))
{
添加(descripber.InvalidUserName(用户名));
}
如果(!string.IsNullOrEmpty(manager.Options.User.AllowedUserNameCharacters),则为else&&
userName.Any(c=>!manager.Options.User.AllowedUserNameCharacters.Contains(c)))
{
添加(descripber.InvalidUserName(用户名));
}
其他的
{
//var owner=await manager.FindByNameAsync(用户名);
var owner=manager.Users.Where(x=>!x.Deleted&&
x、 UserName.ToUpper()==UserName.ToUpper())
.FirstOrDefault();
如果(所有者)=null&&
!string.Equals(wait manager.GetUserIdAsync(所有者),wait manager.GetUserIdAsync(用户)))
{
添加(descripber.DuplicateUserName(用户名));
}
}
}
}
在Startup.cs中
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IUserValidator<ApplicationUser>, CustomUserValidator<ApplicationUser>>();
}
public void配置服务(IServiceCollection服务)
{
services.AddTransient();
}
CustomUserValidator中ValidateAsync方法中的代码工作正常,但原始ValidateAsync似乎也在运行。我之所以这样说,是因为:
提前谢谢。首先让我解释一下这个问题 原因是标识库注入了使用默认库(UserValidator)的validate user类 解决方案只是注入CustomUserValidator。如果它被注入到正常的实现中,它会添加2个UserValidator,第一个是identity库的默认值,第二个是实现CustomUserIdentity的值 然后,要仅注入CustomUserIdentity,必须创建一个新的CustomUserManager,以便能够注入新的ICustomUserValidator,这样它就不会采用默认的IUserValidator 这是我的解决方案: 这是接口ICustomUserValidator
public interface ICustomUserValidator<TUser> : IUserValidator<TUser> where TUser : ApplicationUser
{
}
公共接口ICustomUserValidator:IUserValidator其中TUser:ApplicationUser
{
}
以及类的实现
public class CustomUserValidator<TUser> : UserValidator<TUser>, ICustomUserValidator<TUser>
where TUser : ApplicationUser
{
public async Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user)
{
//Some Code
}
private async Task ValidateUserName(UserManager<TUser> manager, TUser user, ICollection<IdentityError> errors)
{
//Some Code
}
}
公共类CustomUserValidator:UserValidator,ICustomUserValidator
其中TUser:ApplicationUser
{
公共异步任务ValidateAsync(UserManager,TUser用户)
{
//一些代码
}
专用异步任务ValidateUserName(UserManager管理器、TUser用户、ICollection错误)
{
//一些代码
}
}
这张是给CustomUserManager的
public class CustomUserManager<TUser> : UserManager<TUser>
where TUser : ApplicationUser
{
public CustomUserManager(IUserStore<TUser> store, IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<TUser> passwordHasher, IEnumerable<ICustomUserValidator<TUser>> userValidators,
IEnumerable<IPasswordValidator<TUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IServiceProvider tokenProviders,
ILogger<UserManager<TUser>> logger)
: base(
store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors,
tokenProviders, logger)
{
}
}
公共类CustomUserManager:UserManager
其中TUser:ApplicationUser
{
public CustomUserManager(IUserStore存储、IOOptions访问器、,
IPasswordHasher密码hasher,IEnumerable用户验证程序,
IEnumerable PasswordValidator、ILookupNormalizer、keyNormalizer、,
IdentityErrorDescriber错误,IServiceProvider令牌提供程序,
ILogger(记录器)
:基本(
store、OptionAccessor、passwordHasher、userValidators、passwordValidators、keyNormalizer、errors、,
令牌提供者(日志记录器)
{
}
}
请注意,我放置了ICustomUserValidator,而不是IUserValidator
在Startup类中,必须注入新类:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddUserManager<CustomUserManager<ApplicationUser>>()
services.AddIdentity()
.AddEntityFrameworkStores()
.AddUserManager()
最后注入这个类
services.AddTransient<ICustomUserValidator<ApplicationUser>, CustomUserValidator<ApplicationUser>>();
services.AddTransient();
我希望此实现对您有所帮助。在注册身份之前替换默认的UserValidator
services.AddTransient<IUserValidator<ApplicationUser>, CustomUserValidator<ApplicationUser>>(); // before Identity
services.AddDefaultIdentity<ApplicationUser>().AddRoles<Role>()
.AddEntityFrameworkStores<IdentityDbContext>()
.AddDefaultTokenProviders();
services.AddTransient();//身份之前
services.AddDefaultIdentity().AddRoles()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders();
核心3.1中的语法略有不同:
services.AddTransient<IUserValidator<ApplicationUser>, CustomUserValidator>();
services.addtransient在我的例子中,您提到的代码不会被触发。因为我是用一个软删除的用户名创建的,这个用户名也能正常工作。所以,不管是否注释代码,对我来说都不会有什么不同。但是,正如我在第1项中提到的,DuplicateUserName()仍然会被触发,尽管在我调试时不是这样