Есть ли способ передать пользовательскую информацию в IIdentityValidator?

Я работаю над пользовательской проверкой пароля, которая выполнит кучу дополнительных проверок, в том числе и то, что пароль, который пытается создать пользователь, не содержит изменений имени пользователя.

Мы используем Identity Framework, и моей первоначальной целью было просто расширить 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);
    }
}

Но это может принимать только строку в качестве аргумента для UserManager. Есть ли способ также ввести имя пользователя / пользовательский объект здесь или иным образом сравнить строку пароля с именем пользователя перед сохранением информации?

РЕДАКТИРОВАТЬ

Для контекста, именно так устанавливается и используется валидатор паролей.

UserManager:

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);

2 ответа

Решение

Вместо использования PasswordValidator использовать UserValidator что позволит вам использовать ваш пользовательский объект в качестве аргумента. Тип для ValidateAsync исходит из общего параметра.

public class MyUserValidator : IIdentityValidator<User>
{
    public Task<IdentityResult> ValidateAsync(User item)
    {
        ...
    }
}

В вашем usermanager зарегистрируйте его...

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);
Другие вопросы по тегам