验证由分号分隔的IP地址和IP地址范围

时间:2013-09-11 18:17:20

标签: php regex

问题在于,我允许用户输入由分号分隔的IP白名单或IP列表或IP范围。

所以他们可以把

74.122.31.233; 76.233.12.222 - 80.788.888.111; 72.203.44.209
74.122.31.233; 76.233.12.222; 72.203.44.209
74.122.31.233 - 76.233.12.222; 72.203.44.209
74.122.31.233-76.233.12.222; 72.203.44.209
74.122.31.233-76.233.12.222;72.203.44.209

他们可以选择使用空格或不使用空格之间和分号前后的空格。

因此,他们可以将分号或分号分隔的IP地址用分号或IP地址分隔,IP分区用分号分隔。

我是常规表达的新手。有没有人知道正确的方法来验证他们是否正确输入IP白名单以遵守上述规则?

感谢。

4 个答案:

答案 0 :(得分:5)

我不相信正则表达式在这种情况下是必要的甚至是有用的,特别是当PHP有filter_var()时:

function isValid($ranges) {

    // remove all spaces
    $ranges = str_replace(' ', '', $ranges);

    // iterate over individual ranges and IP addresses
    foreach(explode(';', $ranges) as $range) {

        // single address
        if(strpos($range, '-') === false) {
            if(!filter_var($range, FILTER_VALIDATE_IP)) {
                return false;
            }
        }

        // range
        else {
            $addresses = explode('-', $range, 3);

            if(count($addresses) != 2) {
                return false;
            }

            if(!filter_var($addresses[0], FILTER_VALIDATE_IP) || !filter_var($addresses[1], FILTER_VALIDATE_IP)) {
                return false;
            }
        }
    }

    return true;
}

$tests = array(
    '74.122.31.233; 76.233.12.222 - 80.788.888.111; 72.203.44.209',
    '74.122.31.233; 76.233.12.222; 72.203.44.209',
    '74.122.31.233 - 76.233.12.222; 72.203.44.209',
    '74.122.31.233-76.233.12.222; 72.203.44.209',
    '74.122.31.233-76.233.12.222;72.203.44.209');

foreach($tests as $test) {
    echo $test;
    echo isValid($test) ? ' is valid' : ' is invalid';
    echo "\n";
}

输出:

74.122.31.233; 76.233.12.222 - 80.788.888.111; 72.203.44.209 is invalid // 80.788.888.111 is an invalid IP address
74.122.31.233; 76.233.12.222; 72.203.44.209 is valid
74.122.31.233 - 76.233.12.222; 72.203.44.209 is valid
74.122.31.233-76.233.12.222; 72.203.44.209 is valid
74.122.31.233-76.233.12.222;72.203.44.209 is valid

答案 1 :(得分:2)

;分解它们,然后trim数组值以删除空格。这样,您可以确保同等对待用户输入的间隔版本和非间距版本。

$parts = explode(';', $text);
$parts = array_map('trim', $parts);
//or $parts = array_map('trim', explode(';', $text));
//check if IP is valid

要验证IP,您不需要正则表达式。 PHP已经有一个内置函数filter_var(),它完全符合您的要求。

$parts = array_map('trim', explode(';', $text));

foreach ($parts as $ip) {
    if(strpos($ip, '-')) {
        list($range1, $range2) = explode('-', $ip); 
        // validate IP range here
    }    
    elseif (filter_var($ip, FILTER_VALIDATE_IP) ) {
        echo "$ip is valid<br/>";
    }
}

这应该让你开始。

答案 2 :(得分:2)

不要试图将所有内容都塞进一个正则表达式中。我知道你在想,经典菜鸟的错误。

  1. 从输入中删除空格:$input = preg_replace('/\s/', '', $input);
  2. 以分号分隔:$in_arr = explode(';', $input);
  3. 循环遍历数组if( preg_match('/-/', $in_arr[index]) )然后explode('-', $in_arr[index]);,然后像范围一样处理
  4. 验证IP地址不要使用正则表达式。使用ip2long()
    • 每个有效的IP地址实际上都是32位整数,“点分四进制”符号只是将整数分成4到8位的0到25位。
    • 如果您将80.788.888.111这样的无效地址输入ip2long(),则会返回false,不需要复杂的正则表达式。
    • 使用ip2long()使方式更容易比较IP地址,'123.123.123.3' > '123.123.123.10' [字符串比较,错误],但ip2long('123.123.123.3') < ip2long('123.123.123.10') [整数比较,不错]

答案 3 :(得分:1)

这是一个简单的功能:

function validateInput($s) {
    foreach (explode(';', $s) as $v) {
        $v = array_map('trim', explode('-', $v));
        if (count($v) > 2) return false;
        $valid = true;
        foreach ($v as $ip) $valid = $valid && filter_var($ip, FILTER_VALIDATE_IP);
        if (!$valid) return false;
    }
    return true;
}

使用示例:

$inputs = [
    '74.122.31.233; 76.233.12.222 - 80.788.888.111; 72.203.44.209',
    '74.122.31.233; 76.233.12.222; 72.203.44.209',
    '74.122.31.233-76.233.12.222;72.203.44.209',
    '274.122.31.233-76.233.12.222',
    '74.122.31.233-76.233.12.222-77.233.12.222',
];

foreach ($inputs as $input) {
    echo (validateInput($input) ? 'TRUE ' : 'FALSE') . " : $input\n";
}

输出:

FALSE : 74.122.31.233; 76.233.12.222 - 80.788.888.111; 72.203.44.209
TRUE  : 74.122.31.233; 76.233.12.222; 72.203.44.209
TRUE  : 74.122.31.233-76.233.12.222;72.203.44.209
FALSE : 274.122.31.233-76.233.12.222
FALSE : 74.122.31.233-76.233.12.222-77.233.12.222