【问题标题】:Dynamically change PasswordValidator settings Asp.net Mvc动态更改 PasswordValidator 设置 Asp.net Mvc
【发布时间】:2018-10-11 08:03:26
【问题描述】:

我在我的应用程序中管理不同的客户,所有客户都使用相同的 mvc 应用程序。但我需要根据客户更改密码验证逻辑。

我在 IdentityConfig.cs Create 方法中创建了一个默认密码策略,如下所示:

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 方法中使用 Session 变量,或者如何在创建会话后覆盖 PasswordValidator 属性?

【问题讨论】:

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


    【解决方案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...
    

    【讨论】:

    • 谢谢,但我需要访问您在 Create 方法中添加的 if else 块中的会话变量值。是否可以?我可以在 Create 方法中使用变量(对我来说是客户名称)吗?或者我可以在里面发送参数。我需要在 Create 方法的 if else 子句中检查客户并从数据库中获取客户密码策略。每个客户都有自己的密码策略,这些策略存储在数据库中。
    • HttpContext.Current.Session 在 ApplicationUserManager Create 方法中为空。所以我无法访问会话变量。这正是我要问的。如何在 ApplicationUserManager Create 方法中访问会话变量。
    【解决方案2】:

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

    最后,我创建了一个单独的函数,用于获取策略并将它们应用于 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);
       }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多