验证Membership.GeneratePassword

时间:2019-04-30 10:52:56

标签: c# .net regex linq passwords

我正在使用Membership.GeneratePassword()生成随机密码。有时,返回值不符合所需的验证要求。用户还可以提供密码,从而提供验证要求。

我基本上想检查返回的密码,如果它不包含大写字母和小写字母,然后再生成一个数字。

有时候,我的支票显然不是,则返回true。

我已经尝试过RegEx和一些LINQ:

string generatePassword()
{
    password =  System.Web.Security.Membership.GeneratePassword(16, 8);

    if (password.Any(c => char.IsUpper(c)) && password.Any(c => char.IsDigit(c)) && password.Any(c => char.IsLower(c)))
    {
        return password;
    }
    else
    {
       generatePassword();
    }
}


void test() {
    var pattern = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*()_\-+=[{\]};:<>|.\/\?])(?=.{8,})";

    var count = 0;
    for (var i = 0; i < 10000; i++)
    {
        var password = generatePassword();
        if (!Regex.Match(password, pattern).Success)
        {
             Console.WriteLine(password);
             count++;
        }
    }

    Console.WriteLine("There were {0} non matches", count);
}

在我看来,以上代码应始终返回有效的密码。我有一个奇怪的场景,其中它将返回没有数字的密码,因此检查失败,但是如果我对返回的密码在passowrd.Any(char.IsDigit)内执行相同的test,它将说对了。

如果有帮助,密码必须至少为8位数字,包括大写,小写,数字和特殊字符:!@#$%^&*()_-+=[{]};:<>|./?

谢谢。

1 个答案:

答案 0 :(得分:0)

也许您的正则表达式是有效的,但是我认为很难理解它的作用。

考虑使用以下代码,该代码的优点在于,只有在检测到密码有效之前,它才会枚举您的密码。除此之外,它易于理解,易于更改,例如大小至少应为12个字符,或者它不再必须具有大写字符,或者应包含两位数字,...

我将其编程为字符串的扩展方法。如果您确定密码不再是字符串,那么更改将很小。参见extension methods demystified

static bool IsSpecialChar(this char c)
{
    const string specialChars = "!@#$%^&*()_-+=[{]};:<>|./?";
    return specialChars.Contains(c);
}

static bool IsValidPassword(this string password)
{
    // the password needs to be at least 8 characters,
    // contain an uppercase, lowercase, digit and a special char

    // TODO: exception if password == null;
    if (password.Length < 8) return false;

    bool uppercaseDetected = false;
    bool lowercaseDetected = false;
    bool digitDetected = false;
    bool specialCharDetected = false;

    using (IEnumerator<char> enumerator = password.GetEnumerator())
    {
        while (enumerator.MoveNext
           && !(uppercaseDetected && lowercaseDetected 
                 && digitDetected && specialCharDetected))
        {
            // a character is available, and we still don't know if it is a proper password
            char c = enumerator.Current;
            uppercaseDetected = uppercaseDetected || Char.IsUpperCase(c);
            lowercaseDetected = lowercaseDetected || Char.IsLowerCase(c);
            digitDetected = digitDetected || Char.IsDigit(c);
            specialCharDetected = specialCharDetected || c.IsSpecialChar();
        }

        return uppercaseDetected && lowercaseDetected 
            && digitDetected && specialCharDetected;
    }
}

用法:

string GeneratePassword()
{
    string proposedPassword = ...;
    while (!proposedPassword.IsValidPassword())
    {
        proposedPassword = ...;
    }
}

为确保结束,您可以添加一个计数器,并在尝试1000次后停止;或仅添加随机的大写字母/小写字母/特殊字符