0

问题来了,我允许用户输入 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范围用分号分隔。

我是普通快递的新手。有谁知道正确的方法来验证他们是否正确输入了 IP 白名单以遵守上述规则?

谢谢。

4

4 回答 4

6

我不相信正则表达式在这种情况下是必要的甚至是有用的,尤其是 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
于 2013-09-11T18:31:57.707 回答
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/>";
    }
}

那应该让你开始。

于 2013-09-11T18:25:49.290 回答
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 位整数,“点四边形”表示法只是将该整数分成 0-255 的四个 8 位块。
    • 如果你输入一个无效的地址,比如80.788.888.111ip2long()会返回 false,不需要复杂的正则表达式。
    • 使用ip2long()也可以轻松地比较 IP 地址,'123.123.123.3' > '123.123.123.10'[字符串比较,不好],但是ip2long('123.123.123.3') < ip2long('123.123.123.10')[整数比较,好]
于 2013-09-11T18:30:06.160 回答
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
于 2013-09-11T18:49:59.557 回答