默认的会员资格提供程序OnValidatingPassword在自定义实现中必须被覆盖吗?

7
我正在为我的.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;
            }
1个回答

6
MembershipProvider.OnValidatingPassword的文档仅说明当有处理程序注册时,它会引发ValidatingPassword事件,而不是实际验证密码。在反编译器中查看该方法可以证实这一点。
protected virtual void OnValidatingPassword(ValidatePasswordEventArgs e)
{
    if (this._EventHandler != null)
    {
        this._EventHandler(this, e);
    }
}

虽然有些令人困惑,但我相信它的目的是为外部逻辑提供钩子来参与密码验证。自定义提供程序仍需要编写自己的验证逻辑。

如果您查看SQL Membership Provider的源代码(下载提供程序工具包示例),您将看到它包括验证密码的逻辑,并调用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

无论如何,您可以查看 .NET 4 的事件设计指南。页面中间位置,您会找到以下内容:

确保使用受保护的虚拟方法来引发每个事件。

受保护的虚拟方法的名称应与事件名称相同,前缀为 On。例如,名为“TimeChanged”的事件的受保护虚拟方法被命名为“OnTimeChanged”。


我可能没有表达清楚,但当我覆盖基本方法时,我的方法确实被调用了。因此,问题不在于方法是否被调用 - 它似乎只是什么也没做 - pc1oad1etter
通常会创建虚拟方法来引发名为 OnSomeEvent(EventArgs args) 的事件,然后在此处实际引发事件。请参见此答案。因此,OnValidatingEvent并非响应事件,而是引发事件。 - Jeff Ogata
@pc1oad1etter,请查看我的编辑 - 我添加了一个关于OnValidatingPassword名称的更好的信息来源。希望对你有帮助。 - Jeff Ogata
感谢您的时间。让我看看能否总结一下您的立场——基类确实会做一些事情(它会引发事件)。然而,实现者需要自己处理诸如最小密码长度等情况。此外,微软的示例可能不完整或有误,以及我链接的回答说不需要覆盖该方法也是错误的。准确吗? - pc1oad1etter
我将其标记为正确,但听到链接资源中有如此错误的信息,我感到非常惊讶。 - pc1oad1etter
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接