views:

77

answers:

3

I have a password validation script in PHP that checks a few different regular expressions, and throws a unique error message depending on which one fails. Here is an array of the regular expressions and the error messages that are thrown if the match fails:

array(
    'rule1' => array(
        '/^.*[\d].*$/i',
        'Password must contain at least one number.'
    ),
    'rule2' => array(
        '/^.*[a-z].*$/i',
        'Password must contain at least one lowercase letter'
    ),
    'rule3' => array(
        '/^.*[A-Z].*$/i',
        'Password must contain at least one uppercase letter'
    ),
    'rule4' => array(
        '/^.*[~!@#$%^&*()_+=].*$/i',
        'Password must contain at least one special character [~!@#$%^&*()_+=]'
    )
);

For some reason, no matter what I pass through the validation, the "Special Characters" rule fails. I'm guessing it's a problem with the expression. If there's a better (or correct) way to write these expressions, I'm all ears!

+6  A: 

I can't see a problem with your special characters regular expression, but I can see a problem with the upper and lower case checks:

/^.*[A-Z].*$/i

The i at the end means PCRE_CASELESS, i.e. it will ignore case. You should omit the i.

Mark Byers
Way to roll a nice spot check!
LeguRi
Grr.. Beat me to it. In fact, he should remove them from all four of his regex as they are either circumventing their intended purpose or they are completely irrelevant to the search (special chars/numbers).
webbiedave
@webbiedave. Yep, also the `[...]` around `\d` are unnecessary. :)
Mark Byers
And he should remove both the `.*`, `^` and `$` as they are just emulating the functionality of `/[A-Z]/`
webbiedave
Marked this answer as correct since it, plus the comments, contains the most help. I've implemented all of the suggestions to clean up the redundancies. Turns out the problem was worthy of a big FACEPALM. I was hashing the password prior to testing for validation. Thanks for the help, anyway!
Stephen
Team effort. Glad we could help.
webbiedave
A: 

This works (as seen on rubular.com):

(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[~!@#$%^&*()_+=]).*

This uses lookahead (which is supported by PHP's preg functions, since they're PCRE) instead of matching all the different rules. I'm not sure why yours doesn't work.

References

polygenelubricants
+1  A: 

The regex should simply be:

/[~!@#$%^&*()_+=]/

No need for the stars. Either way your regex should work.

I would check the function that's using the array to see if there are any logic errors.

Also, as Mark Byers stated, you should remove the insensitive modifiers /i

webbiedave
To develop, all the /^.* .*$/ you do can be replaced by / /
Arkh
@Arkh: Yes. Good suggestion.
webbiedave