首页 > 解决方案 > 动态更改 PasswordValidator 设置 Asp.net Mvc

问题描述

我在我的应用程序中管理不同的客户,所有客户都使用相同的 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.netasp.net-mvcasp.net-identity

解决方案


您可以通过扩展创建自己的自定义密码验证器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


现在,您拥有CustomPasswordValidator1and 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...

推荐阅读