1
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?

2
  • 7
    xkcd.com/936 Commented Sep 5, 2013 at 16:06
  • There are tons of regex tester pages out there. Many will highlight matching portions in your test string. Commented Sep 5, 2013 at 16:09

2 Answers 2

8

Use preg_* instead, and a better validation string

There are (at least) 3 issues with the regex you're using:

  1. You're currently needlessly checking for (?=.*[^a-zA-Z0-9]) when there is a better option to do this - [\W_].
  2. You're checking for at least 7 characters and no more than 19, rather than at least 8.
  3. You're using a deprecated function.
  4. Your function allows whitespace in passwords.

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.

Sign up to request clarification or add additional context in comments.

3 Comments

It will fail if the pswd contains an underscore, it is not what the OP wants. (?=.*[^a-zA-Z0-9]) is mandatory to match special char.
@M42 Fixed. I even wrote the comment then didn't add the underscore to the capture group for special chars.
In the first sentence, did you mean to say he should use preg_match()? You certainly aren't using preg_replace() yourself.
4

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.

2 Comments

This can also be done in a foreach loop with an array of validators, and is how I'd normally do it. +1.
Have added a PHP-esque way of doing this in my answer, credited you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.