Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex to match multiple patterns in any order

I'm validating a password for complexity in an ASP.NET MVC3 app. My current requirements are that it must contain at least one upper case letter, one lower case letter, one digit and no more than three repeated characters. I'd like to generalise those numbers though, and also add a condition for non-alphanumeric characters.

At present, I'm validating server-side only, so I'm able to call Regex.IsMatch multiple times using one regex for each condition. I want to be able to validate client-side too though. because unobtrusive jQuery validation will only allow one regex, I need to combine all five conditions into a single pattern.

I don't know much when it comes to regular expressions but I've been doing a bit of reading recently. I may be missing something simple but I can't find a way to AND multiple patterns together the way a | will OR them.

like image 911
jmcilhinney Avatar asked Jan 25 '11 08:01

jmcilhinney


1 Answers

You can do this (in .NET) with several lookahead assertions in a single regex:

^(?=.*\p{Lu})(?:.*\p{Ll})(?=.*\d)(?=.*\W)(?!.*(.).*\1.*\1)

will match if all conditions are true.

^                  # Match the start of the string
(?=.*\p{Lu})       # True if there is at least one uppercase letter ahead
(?=.*\p{Ll})       # True if there is at least one lowercase letter ahead
(?=.*\d)           # True if there is at least one digit ahead
(?=.*\W)           # True if there is at least one non-alnum character ahead
(?!.*(.).*\1.*\1)  # True if there is no character repeated twice ahead

Note that the match is not going to consume any characters of the string - if you want the match operation to return the string you're matching against, add .* at the end of the regex.

In JavaScript, you can't use Unicode character properties. So instead you could use

^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[\W_])(?!.*(.).*\1.*\1)

which will of course only use ASCII letters for validation. If that's OK for you, fine. You could go and augment the character classes like [A-ZÄÖÜÀÈÌÒÙÁÉÍÓÚ] etc. etc. but you would probably never be complete with this. On the server side, if you want the validation to yield the same result, you'd have to specify RegexOptions.ECMAScript so the .NET regex engine behaves like the JavaScript engine (thanks Alan Moore for noticing!).

like image 196
Tim Pietzcker Avatar answered Oct 22 '22 20:10

Tim Pietzcker