Нужно ли переопределить OnValidatingPassword поставщика членства по умолчанию в пользовательских реализациях?

Я работаю над внедрением специального поставщика членства для моего приложения .net. Я настроил конфигурацию для минимального количества символов и не буквенно-цифровых символов, но, похоже, он все равно пропускает пароли, даже если они нарушают правила.

OnValidatingPassword - это виртуальный метод. Пример от Microsoft не переопределить метод.

Этот вопрос решает ту же проблему, но автор отказался от ответа. получить ответ на свой вопрос и просто отвергнуть функцию. В этом ответе говорится, что нет необходимости переопределять функция, чтобы это работало.

Базовая функция ничего не делает? Когда я переопределяю OnValidatePassword и просто вызываю базовый класс, моя функция срабатывает, но она никогда не отклоняет мои слишком простые пароли.

Пример кода (с настраиваемой функцией CreateUser)

protected override void OnValidatingPassword(ValidatePasswordEventArgs e)
        {                        
             base.OnValidatingPassword(e);
        }
        //
        // MembershipProvider.CreateUser
        //
        public MembershipUser CreateUser(string username, string password, string globalIdentifier, string firstName, string lastName, 
            string birthDate, object providerUserKey, out MembershipCreateStatus status)
        {
            ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(username, password, true);
            OnValidatingPassword(args);

            if (args.Cancel)
            {
                status = MembershipCreateStatus.InvalidPassword;
                return null;
            }

person pc1oad1etter    schedule 04.10.2011    source источник


Ответы (1)


В документации для MembershipProvider.OnValidatingPassword только указано, что он вызывает событие ValidatingPassword, если обработчик зарегистрирован, а не то, что он фактически проверяет пароль.

Взгляд на метод в Reflector подтверждает это:

protected virtual void OnValidatingPassword(ValidatePasswordEventArgs e)
{
    if (this._EventHandler != null)
    {
        this._EventHandler(this, e);
    }
}

Это сбивает с толку, но я считаю, что цель состоит в том, чтобы обеспечить возможность внешней логики участвовать в проверке пароля; Пользовательскому провайдеру все равно потребуется написать собственную логику проверки.

Если вы посмотрите исходный код для поставщика членства в SQL (загрузите Provider Toolkit Samples), вы увидите, что он включает логику для проверки пароля, а также вызывает OnValidatingPassword. Следующий код взят из метода CreateUser:

if( password.Length < MinRequiredPasswordLength )
{
    status = MembershipCreateStatus.InvalidPassword;
    return null;
}

int count = 0;

for( int i = 0; i < password.Length; i++ )
{
    if( !char.IsLetterOrDigit( password, i ) )
    {
        count++;
    }
}

if( count < MinRequiredNonAlphanumericCharacters )
{
    status = MembershipCreateStatus.InvalidPassword;
    return null;
}

if( PasswordStrengthRegularExpression.Length > 0 )
{
    if( !Regex.IsMatch( password, PasswordStrengthRegularExpression ) )
    {
        status = MembershipCreateStatus.InvalidPassword;
        return null;
    }
}

ValidatePasswordEventArgs e = new ValidatePasswordEventArgs( username, password, true );
OnValidatingPassword( e );

if( e.Cancel )
{
    status = MembershipCreateStatus.InvalidPassword;
    return null;
}

Изменить

Я думаю, что часть путаницы связана с именем OnValidatingPassword, и это, похоже, подразумевает, что он обрабатывает проверку пароля, а не создает событие, позволяющее другому коду проверять пароль. Как бы то ни было, я понимаю путаницу - наверное, было бы понятнее, если бы метод был назван RaiseValidatingPasswordEvent.

В любом случае вы можете ознакомиться с рекомендациями Event Design для .NET 4. Примерно на полпути к страницу, вы найдете это:

Используйте защищенный виртуальный метод для создания каждого события.

Имя защищенного виртуального метода должно совпадать с именем события с префиксом On. Например, защищенный виртуальный метод для события с именем «TimeChanged» называется «OnTimeChanged».

person Jeff Ogata    schedule 04.10.2011
comment
Возможно, я не ясно дал понять, но когда я переопределяю базовый метод, мой метод вызывается. Так что вопрос не в том, будет ли вызван метод - просто кажется, что он ничего не делает - person pc1oad1etter; 05.10.2011
comment
Правильно - он не делает ничего, кроме вызова события ValidatingPassword. OnValidatingPassword не выполняет никаких проверок. - person Jeff Ogata; 05.10.2011
comment
Спасибо за ответ. Как OnValidatingEvent может нести ответственность за возникновение события ValidatingPassword - разве он не отвечает на событие ValidatingPassword? - person pc1oad1etter; 05.10.2011
comment
Обычно создают виртуальные методы для создания событий с именем OnSomeEvent(EventArgs args), а затем фактически вызывают событие там. См. Этот ответ. Итак, OnValidatingEvent не реагирует на событие, а вызывает его. - person Jeff Ogata; 05.10.2011
comment
@ pc1oad1etter, пожалуйста, посмотрите мою правку - я добавил лучший источник информации относительно имени OnValidatingPassword. HTH. - person Jeff Ogata; 05.10.2011
comment
Спасибо за ваше время. Позвольте мне посмотреть, смогу ли я резюмировать вашу позицию - базовый класс что-то делает (вызывает событие). Однако разработчик должен самостоятельно обрабатывать даже такие случаи, как минимальная длина пароля. Кроме того, пример Microsoft либо неполный, либо ошибочный, как и ответ, который я связал, в котором говорится, что не нужно переопределять метод. Точный? - person pc1oad1etter; 07.10.2011
comment
@ pc1oad1etter да, это так. Я считаю, что этот пример неверен - нигде нет кода, который действительно проверяет пароль, и мы знаем, что MembershipProvider этого не делает. Ответ, с которым вы связались, правильный - вы можете переопределить OnValidatingPassword и поместить туда свою логику проверки, но вы не должны - см. Мой следующий комментарий. - person Jeff Ogata; 07.10.2011
comment
Другие способы сделать это вместо переопределения OnValidatingPassword: (1) прикрепить обработчик к событию ValidatingPassword с логикой проверки и позволить базе MembershipProvider.OnValidatingPassword вызвать его, (2) поместить логику проверки в метод CreateUser (как это делает SqlMembershipProvider) или (3) поместите логику проверки в отдельный метод в вашем провайдере и вызовите этот метод из CreateUser, ChangePassword и из любого другого места, где вам может потребоваться проверка пароля. - person Jeff Ogata; 07.10.2011
comment
Я отмечаю это как правильное, но очень удивлен, узнав, что на связанных ресурсах содержится такая дезинформация. - person pc1oad1etter; 07.05.2012