这个PHP正则表达式进行密码验证有什么问题?

时间:2013-09-05 16:01:39

标签: php regex

ereg("/^(?=.*[a-z])(?=.*[0-9])(?=.*[^a-zA-Z0-9])(?=.*[A-Z]).{7,19}$/","ABCabc123!!");

这应该是一个密码验证器,需要大写和小写的字母以及数字特殊字符和最小长度为8 ....但上面的返回false。我做错了什么?

2 个答案:

答案 0 :(得分:8)

改为使用preg_*,以及更好的验证字符串

您正在使用的正则表达式(至少)有3个问题:

  1. 当有更好的选择时,您目前正在不必要地检查(?=.*[^a-zA-Z0-9]) - [\W_]
  2. 您要检查至少7个字符且不超过19,而不是至少8
  3. 您正在使用a deprecated function
  4. 您的函数允许使用密码中的空格。
  5. 这应该对你更好:

    $regex = "/^\S*(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[\d])(?=\S*[\W_])(?=\S{8,})\S*$/";
    $valid = (bool) preg_match($regex,$password);
    

    此正则表达式的组件说明:

    /            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
    

    正如安迪莱斯特所指出的,你可能会因为多次检查而感觉更好

    正如安迪所说,你最好存储一堆规则。这允许您定制错误消息并轻松添加规则。在PHP中,我将以这种方式实现它:

    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;
    }
    

    可以找到实时演示here

答案 1 :(得分:4)

不要试图在一个正则表达式中完成所有操作。进行多次正则表达式检查。

我知道你正在编写PHP,但我更了解Perl,所以请继续学习。

my $password_is_valid =
    length($pw) >= 8 &&  # Length >= 8
    ($pw =~ /[a-z]/) &&  # Has lowercase
    ($pw =~ /[A-Z]/) &&  # Has uppercase
    ($pw =~ /\W/);       # Has special character

当然,这需要五行而不是一行,但是在你回去并且必须添加新规则或者弄清楚代码的作用的一年中,你会很高兴你这样编写它。也许你以后需要一个数字。简单!

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

仅仅因为你可以在一个正则表达式中执行它并不意味着你应该