首页 > 解决方案 > 有没有一种简单的方法来比较 PHP 中的 IP?

问题描述

一方面,我有一个类似的 IP 123.3.2.3,我想将它与一系列允许的 IP 进行比较,例如:

$allowedIps = ['123.*.*.*', '123.3.2.3', '123.3.2.3::1', '123.3.*.3']

在这种情况下,它应该匹配所有项目。

有没有一种简单的方法可以做到这一点而不必创建复杂的字符串比较算法?

标签: phpip

解决方案


如果您不打算使用通配符 as ,这将匹配和123.3.2*.3之间的任何 IP ,那么下面的解决方案可以正常工作。123.3.20.3123.3.29.3

循环遍历数组中的 IP,如果其中存在通配符,则创建两个新 IP - 一个将通配符*替换为 0,另一个替换为 255。这是下限和上限。然后使用该ip2long()函数将其转换为整数,而不是 IP 字符串。在 IP 本身以及循环它们时数组中的值都执行此操作。

然后只是比较它们,它实际上是在上限和下限之间。

如果字符串中没有通配符,则进行直接比较。

$allowedIps = ['123.2.*.*', '123.3.2.3', '123.3.*.3'];
$IP = '123.3.1.3';
$match = 0;

foreach ($allowedIps as $allowed) {
    // If there is no wildcard, we check for the specific IP instead, and not a range
    if (strpos($allowed, "*") !== false) {
        $lowest = str_replace("*", "0", $allowed);
        $highest = str_replace("*", "255", $allowed);

        if (ip2long($IP) >= ip2long($lowest) && ip2long($IP) <= ip2long($highest)) {
            echo "$IP matched $allowed";
            $match = 1;
            break;
        }
    } elseif (ip2long($IP) === ip2long($allowed)) {
        echo "Matched ".$allowed;
        $match = 1;
        break;
    }
}

可能甚至不需要条件来检查是否有通配符,因为它不会替换任何内容,并且后续if条件中的两个条件都为真。

公平警告,我尚未对此进行全面测试,并且可能存在一些条件可能失败的模糊情况。在 PHP 之外执行此操作可能会更好。


推荐阅读