A Pattern for Validating Password Fields
Users should, in theory, be allowed to pick whatever password they want, without it being required to contain at least one number of special character, for example.
But, in the event such criteria are required, here’s a regular expression to check for validity
<input type="password" required minlength="6" pattern="(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[\x20-\x2f][\x3a-\x40][\x5b-\x60][\x7b-\x7e]).*" />
What’s going on with that pattern?
It heavily employs the positive lookahead assertion. Breaking the regex into parts we have:
(?=.*[A-Z])
(?=.*[a-z])
(?=.*[0-9])
(?=.*[\x20-\x2f][\x3a-\x40][\x5b-\x60][\x7b-\x7e])
.*
Which relate to capitals, lowercase letters, numbers and ASCII special characters.
The expression /a(?=b)/
matches a
only when it is immediately followed by b
. Moreover, it doesn’t include the b
in the match, and will continue its search from the end of the a
, not the end of the b
.
/a(?=.*b)/
matches an a
if there is a b
anywhere after it in the expression.
/a(?=.*b)(?=.*c)/
matches an a
if and only if there exists both a b
and a c
somewhere after it. Crucially, because after matching the b
the regex engine tracks all the way back to the a
, it will match the c
even if it occurs before the b
. So it has the potential to match both ...a...b...c...
and ...a...c...b
.
Dropping the first a
from the expression, /(?=.*b)(?=.*c)/
matches any string that contains at least one b
and one c
, in any order. /(?=.*[A-Z])(?=.*[a-z])/
matches any string with at least one upercase and one lowercase letter.
After all those positive lookaheads, no characters have actually been consumed in the regular expression, so in order for it to be used as a pattern
attribute, a .*
is tacked on the end to consume the rest of the characters after the match is made.
So there we have a pattern for requiring a password with at lease one lowercase letter, one uppercase, a number and a special character.