ereg("/^(?=.*[a-z])(?=.*[0-9])(?=.*[^a-zA-Z0-9])(?=.*[A-Z]).{7,19}$/","ABCabc123!!");
This is supposed to be a password validator, requiring alphabets in upper and lowercases along with numbers special chars and mininmum length of 8....but the above returns false. What am I doing wrong?
preg_*
instead, and a better validation string There are (at least) 3 issues with the regex you're using:
(?=.*[^a-zA-Z0-9])
when there is a better option to do this - [\\W_]
. 7
characters and no more than 19
, rather than at least 8
. This should work better for you:
$regex = "/^\S*(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[\d])(?=\S*[\W_])(?=\S{8,})\S*$/";
$valid = (bool) preg_match($regex,$password);
Explanation of the components of this regex:
/ Delimiter
^ Start of string anchor
\S* Any string without whitespace
(?=\S*[a-z]) Must contain at least 1 lowercase letter
(?=\S*[A-Z]) Must contain at least 1 uppercase letter
(?=\S*[\d]) Must contain at least 1 digit
(?=\S*[\W_]) Must contain at least 1 special character
(note: \W will not consider underscore '_' a special character)
(?=\S{8,}) Must contain at least 8 characters
$ End of string anchor
As pointed out by Andy Lester, you may be better off with multiple checks
As Andy mentioned, you're best off storing a bunch of rules. This allows you to tailor your error messages and add rules easily. In PHP I'd implement this in this way:
function validatePassword($password) {
$rules = array(
'no_whitespace' => '/^\S*$/',
'match_upper' => '/[A-Z]/',
'match_lower' => '/[a-z]/',
'match_number' => '/\d/',
'match_special' => '/[\W_]/',
'length_abv_8' => '/\S{8,}/'
);
$valid = true;
foreach($rules as $rule) {
$valid = $valid && (bool) preg_match($rule, $password);
if($valid !== true) break;
}
return (bool) $valid;
}
Live demonstration can be found here .
Don't try to do it all in one regex. Make multiple regex checks.
I know you're writing PHP, but I know Perl better, so follow along and get the idea.
my $password_is_valid =
length($pw) >= 8 && # Length >= 8
($pw =~ /[a-z]/) && # Has lowercase
($pw =~ /[A-Z]/) && # Has uppercase
($pw =~ /\W/); # Has special character
Sure, that takes up five lines instead of one, but in a year when you go back and have to add a new rule, or figure out what the code does, you'll be glad you wrote it that way. Maybe you require a digit later on. Easy!
my $password_is_valid =
length($pw) >= 8 && # Length >= 8
($pw =~ /\d/) && # Has digit
($pw =~ /[a-z]/) && # Has lowercase
($pw =~ /[A-Z]/) && # Has uppercase
($pw =~ /\W/); # Has special character
Just because you can do it in one regex doesn't mean you should .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.