我正在我的应用程序中管理不同的客户,并且所有客户都使用相同的 mvc 应用程序。但是我需要根据客户更改密码验证逻辑。
我在 IdentityConfig 中创建了一个默认密码策略.cs 创建方法,如下所示:
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(context.Get<ApplicationDbContext>());
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
return manager;
}
但是我需要管理密码验证器客户特定。我正在从子域获取当前客户,我的意思是如果我的 url http://example.com/customer1,那么我知道这是 customer1 并从数据库中获取密码策略设置。我将这些设置放入会话变量中。我可以在 IdentityConfig Create 方法中使用会话变量,或者如何在创建会话后覆盖 PasswordValidator 属性?
您可以通过扩展IIdentityValidator
来创建自己的自定义密码验证器:
// your first validator logic
public class CustomPasswordValidator1: IIdentityValidator<string>
{
public CustomPasswordValidator1(int length)
{
RequiredLength = length;
}
public int RequiredLength { get; set; }
public Task<IdentityResult> ValidateAsync(string password)
{
// write your own validation logic here
if (string.IsNullOrEmpty(password) || password.Length < RequiredLength)
{
return Task.FromResult(IdentityResult.Failed("bad password"));
}
// good password
return Task.FromResult(IdentityResult.Success);
}
}
// your second validator logic
public class CustomPasswordValidator2: IIdentityValidator<string>
{
public CustomPasswordValidator2(int length)
{
RequiredLength = length;
}
public int RequiredLength { get; set; }
public Task<IdentityResult> ValidateAsync(string password)
{
// write some other validation logic
}
}
有关如何扩展IIdentityValidator
的更多信息,请参阅此处
现在,您已经有了CustomPasswordValidator1
和CustomPasswordValidator2
,您可以更改ApplicationUserManager
代码,并使用正确的验证器逻辑:
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new CustomUserStore(context.Get<ApplicationDbContext>()));
manager.UserValidator = new UserValidator<ApplicationUser, long>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
if (/* some condition */)
{
manager.PasswordValidator = new CustomPasswordValidator1(6 /*min length*/ );
}
else
{
manager.PasswordValidator = new CustomPasswordValidator2(12 /*min length*/);
}
// more code...
在管理器中定义验证器时,我遇到了类似的问题。一旦完成,它们似乎就无法再调整了。
最后,我创建了一个单独的函数,在其中获取策略并将它们应用于IdentityOpions。之后,我可以使用这些选项创建验证器并将其添加到管理器中。似乎验证器将选项作为默认值考虑在内,而不是允许您即时调整它们。
public class ApplicationUserManager : UserManager<ApplicationUser>
{
internal void SetPolicies(Dictionary<string, string> passwordPolicies)
{ // do stuff in a loop, like getting the policies like this:
Options.Password.RequireDigit = policy.value;
// Then create and add the validator with the new policies in place.
_passwordValidator = new PasswordValidator<ApplicationUser>();
this.PasswordValidators.Add(_passwordValidator);
}
}