验证 Membership.GeneratePassword
Validating Membership.GeneratePassword
我正在使用 Membership.GeneratePassword() 生成随机密码。有时 returned 值不符合所需的验证要求。用户还可以提供密码,因此需要验证。
我基本上想检查 returned 密码,如果它不包含大写字母、小写字母和数字,则生成另一个。
有时我的支票会 return 正确,但显然不是。
我尝试过 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);
}
在我看来,上面的密码应该总是 return 一个有效的密码。我有一个奇怪的场景,其中它将 return 一个没有数字的密码,因此检查失败,但是如果我在 test
内部对 returned 密码,它会说是真的。
如果有帮助,密码需要至少8位,包含大写、小写、数字和一个特殊字符:!@#$%^&*()_-+=[{]};:<>|./?
谢谢。
也许您的正则表达式是有效的,但我认为很难理解它的作用。
考虑使用下面的代码,它的优点是它只会枚举您的密码,直到它检测到它是有效的。此外,它易于理解,易于进行小的更改,例如大小至少应为 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 次后停止;或者只是添加一个随机的 Uppercase / LowerCase / SpecialChar
我正在使用 Membership.GeneratePassword() 生成随机密码。有时 returned 值不符合所需的验证要求。用户还可以提供密码,因此需要验证。
我基本上想检查 returned 密码,如果它不包含大写字母、小写字母和数字,则生成另一个。
有时我的支票会 return 正确,但显然不是。
我尝试过 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);
}
在我看来,上面的密码应该总是 return 一个有效的密码。我有一个奇怪的场景,其中它将 return 一个没有数字的密码,因此检查失败,但是如果我在 test
内部对 returned 密码,它会说是真的。
如果有帮助,密码需要至少8位,包含大写、小写、数字和一个特殊字符:!@#$%^&*()_-+=[{]};:<>|./?
谢谢。
也许您的正则表达式是有效的,但我认为很难理解它的作用。
考虑使用下面的代码,它的优点是它只会枚举您的密码,直到它检测到它是有效的。此外,它易于理解,易于进行小的更改,例如大小至少应为 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 次后停止;或者只是添加一个随机的 Uppercase / LowerCase / SpecialChar