Creating a regex to check for a strong password

2020-07-27 03:58发布

问题:

Say I have a regex that checks for alphanumeric.

I now want to create another regex that checks for at least 1 number in the password. And I want to check if it has at least 1 non-alphanumeric character (somethign other than a letter or number).

Should I just call each one seperatley, and if one fails return false or is there a way to combine them into 1 call?

回答1:

Depends on exactly what criteria you're using, but it would probably be better to do a single pass through the string and set a number of flags based on what you've seen:

  • hasDigit
  • hasAlpha
  • hasSymbol
  • etc

Then use these at the end to decide if the password is complex enough.

Even Better:

As lexu suggests, using counts instead of flags would allow greater flexibility.



回答2:

I would compose small methods using &&:

internal bool HasDigit(string password) { .. }
internal bool HasNonAlpha(string password) { .. }

bool IsStrong(string password) {  
   return HasDigit(password) && HasNonAlpha(password);
}   


回答3:

I think this is what you're looking for:

^.{6,}(?<=\d.*)(?<=[^a-zA-Z0-9].*)$

(will match a password with a minimum length of 6, with at least one digit and one non-alphanumerical character)

In code:

public bool PasswordOk(string pwd) 
{
    return Regex.IsMatch(pwd,@"^.{6,}(?<=\d.*)(?<=[^a-zA-Z0-9].*)$");
}


回答4:

You should use two calls. For a bit more advanced testing you can use The password meter. It is freely available for distribution under GPL.



回答5:

IMHO, it's a question of style whether to make one or two statements from it.

Why not check for it in any of the two orders that they may appear. (As regular expressions go, we don't have something like a counter for braces or parantheses, thus we have to honor the possible ordering of things.

That one might work for perl:

(\d.*[^[:alnum:]])|([^[:alnum:]].*\d)

Might be easier to read to make two statements from it, especially because then every semantical condition is only occurring once.



回答6:

You add an | (or) operator into the regex e.g.

[0-9]|[A-Z]



回答7:

Regex is not the fastest way.

Give this a try:

string Password = "Pass12!";

bool ValidPassword = Password.Any(char.IsDigit)
    && !Password.All(char.IsLetterOrDigit)
    && Password.Length >= 6;

Instead of:

string Password = "Pass12!";

bool ValidPassword = Regex.IsMatch(Password, @"^.{6,}(?<=\d.*)(?<=[^a-zA-Z0-9].*)$");

I you iterate through it 1 million times it will take the first 157ms and the second 1251ms.

And the most important thing the others said already: much better to maintain.