动态更改PasswordValidator设置Asp.net Mvc

时间:2018-10-11 08:03:27

标签: asp.net asp.net-mvc asp.net-identity

我在我的应用程序中管理不同的客户,并且所有客户都在使用相同的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;
    }

但是我需要管理特定于客户的PasswordValidator。我正在从子域中获取当前客户,我的意思是如果我的URL是http://example.com/customer1,那么我知道这是customer1并从数据库中获取密码策略设置。我将这些设置放入Session变量中。我可以在IdentityConfig Create方法中使用会话变量,还是在创建会话后如何覆盖PasswordValidator属性?

2 个答案:

答案 0 :(得分:1)

您可以通过扩展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
    }
}

See here,了解有关如何扩展IIdentityValidator

的更多信息

现在,您拥有CustomPasswordValidator1CustomPasswordValidator2,可以更改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...

答案 1 :(得分:0)

在管理器中定义验证器时遇到了类似的问题。完成后,它们似乎不再可以调整了。

最后,我创建了一个单独的功能,可以在其中获取策略并将其应用于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);
   }
}