我正在研究一个自定义密码验证,它将进行一系列额外的检查,理想情况下包括用户尝试创建的密码不包含其用户名的任何排列。
我们正在使用身份框架,我的初衷是像这样扩展IIdentityValidator:
public class StrongPasswordValidator : IIdentityValidator<string>
{
public int MinimumLength { get; set; }
public int MaximumLength { get; set; }
public void CustomPasswordValidator(int minimumLength, int maximumLength)
{
this.MinimumLength = minimumLength;
this.MaximumLength = maximumLength;
}
public Task<IdentityResult> ValidateAsync(string item)
{
if (item.Length < MinimumLength)
{
return Task.FromResult(IdentityResult.Failed("Password must be a minimum of " + MinimumLength + " characters."));
}
if (item.Length > MaximumLength)
{
return Task.FromResult(IdentityResult.Failed("Password must be a maximum of " + MaximumLength + " characters."));
}
return Task.FromResult(IdentityResult.Success);
}
}
但这只能将字符串作为每个用户管理器的参数。有没有办法在这里也拉入用户名/自定义对象,或者在保留信息之前将密码字符串与用户名进行比较?
编辑
对于上下文,这是密码验证器的设置和使用方式。
用户管理员:
public CustomUserManager(IUserStore<User> store,
IPasswordHasher passwordHasher,
IIdentityMessageService emailService)
: base(store)
{
//Other validators
PasswordValidator = new StrongPasswordValidator
{
MinimumLength = 8,
MaximumLength = 100
};
PasswordHasher = passwordHasher;
EmailService = emailService;
}
用户创建:
var userManager = new CustomUserManager(userStore,
new BCryptHasher(), emailService.Object);
userManager.CreateAsync(user, Password);
不要使用PasswordValidator
而是使用 UserValidator
,这将允许您使用用户对象作为参数。ValidateAsync
的类型来自泛型参数。
public class MyUserValidator : IIdentityValidator<User>
{
public Task<IdentityResult> ValidateAsync(User item)
{
...
}
}
在您的用户管理器中注册它...
public ApplicationUserManager(IUserStore<User> store)
: base(store)
{
UserValidator = new MyUserValidator<User>(...);
}
只需在 StrongPasswordValidator
中添加一个或多个您希望类型的字段,并在构造函数中注入值
public class StrongPasswordValidator : IIdentityValidator<string>
{
public int MinimumLength { get; set; }
public int MaximumLength { get; set; }
private readonly MyCustomObjectType _myCustomObject;
public void CustomPasswordValidator(int minimumLength, int maximumLength,
MyCustomObjectType myCustomObject)
{
// guard clause
if(myCustomObject == null)
{
throw new ArgumentExpcetion("myCustomObject was not provided.");
}
_myCustomObject = myCustomObject;
this.MinimumLength = minimumLength;
this.MaximumLength = maximumLength;
}
public Task<IdentityResult> ValidateAsync(string item)
{
// use _myCustomObject here
if (item.Length < MinimumLength)
{
return Task.FromResult(IdentityResult.Failed("Password must be a minimum of " + MinimumLength + " characters."));
}
if (item.Length > MaximumLength)
{
return Task.FromResult(IdentityResult.Failed("Password must be a maximum of " + MaximumLength + " characters."));
}
return Task.FromResult(IdentityResult.Success);
}
}
现在,当您创建 StrongPasswordValidator
的实例时,您可以注入自定义对象。
MyCustomObjectType myCustomObject = new MyCustomObjectType();
UserManager.PasswordValidator = new StrongPasswordValidator(6, 10, myCustomObject);
编辑
根据更新的帖子,是什么阻止您通过将所需的对象传递给其构造函数来更新StrongPasswordValidator
。
public CustomUserManager(IUserStore<User> store,
IPasswordHasher passwordHasher,
IIdentityMessageService emailService)
: base(store)
{
//Other validators
MyCustomObjectType myCustomObject = new MyCustomObjectType();
PasswordValidator = new StrongPasswordValidator(8, 100, myCustomObject);
PasswordHasher = passwordHasher;
EmailService = emailService;
}
然后创建一个用户。
var userManager = new CustomUserManager(userStore,
new BCryptHasher(), emailService.Object);
userManager.CreateAsync(user, Password);