php判断数组里面的每个ip是否在给定的另一组ip数组段内

php判断数组里面的每个ip是否在给定的另一组ip数组段内,两个数组里面可能同时含有ipv4和ipv6:

namespace App\Helpers;

class IpValidator
{
    public function isIpInRange($ip, $ranges)
    {
        foreach ($ranges as $range) {

            if (strpos($range, '-') !== false) {

                // 是起止IP格式
                [$start, $end] = explode('-', $range);

                if ($this->ipInRange($ip, $start, $end)) {
                    return true;
                }

            } else {
                // 是CIDR格式
                [$prefix, $length] = explode('/', $range);

                if ($this->ipInCidr($ip, $prefix, $length)) {
                    return true;
                }

            }

        }

        return false;

    }

    public function ipInRange($ip, $start, $end)
    {
        // 实现逻辑
        return ip2long($ip) >= ip2long($start) && ip2long($ip) <= ip2long($end);

    }

    public function ipInCidr($ip, $net, $bits)
    {
        // 实现逻辑
        return (ip2long($ip) & ~0 << (32 - $bits)) == ip2long($net);

    }

    public function isIpv6InRange($ipv6, $ranges)
    {

        foreach ($ranges as $range) {
            // 提取网络前缀和掩码长度
            [$prefix, $length] = explode('/', $range);

            // 提取给定IPv6和网络前缀的网络部分
            $givenNetPrefix = substr($ipv6, 0, strpos($ipv6, ':'));
            $rangeNetPrefix = substr($prefix, 0, strpos($prefix, ':'));

            // 比较网络前缀是否匹配
            if ($givenNetPrefix === $rangeNetPrefix) {
                // 获取给定IPv6地址长度
                $givenLength = strlen($ipv6) - strpos($ipv6, ':');

                // 判断是否小于等于网络掩码长度
                if ($givenLength <= $length) {
                    return true;
                }
            }
        }

        return false;
    }

    public function separateIpRanges($ipRanges)
    {

        $ipv4Ranges = [];
        $ipv6Ranges = [];

        foreach ($ipRanges as $range) {

            // 按逗号分隔多个范围
            if (strpos($range, '-') !== false) {
                $start_ip = explode('-', $range)[0];
            }
            if (strpos($range, '/') !== false) {
                $start_ip = explode('/', $range)[0];
            }

            $segment = trim($start_ip);

            if (filter_var($segment, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {

                // 是IPv6范围
                $ipv6Ranges[] = $range;

            } else {

                // 是IPv4范围
                $ipv4Ranges[] = $range;

            }

        }

        return [
            'ipv4' => $ipv4Ranges,
            'ipv6' => $ipv6Ranges,
        ];

    }

    public function validateIps($ipArray, $ipRanges)
    {
        $ipv4Ranges = $this->separateIpRanges($ipRanges)['ipv4'];
        $ipv6Ranges = $this->separateIpRanges($ipRanges)['ipv6'];

        $notInIps = [];

        foreach ($ipArray as $ip) {
            $ipVersion = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? 6 : 4;

            if ($ipVersion == 4) {
                $res = $this->isIpInRange($ip, $ipv4Ranges);
            } else {
                $res = $this->isIpv6InRange($ip, $ipv6Ranges);
            }

            if (!$res) {
                $notInIps[] = $ip;
            }
        }

        return $notInIps;
    }

}

使用方式:


$ipArray = [
    '101.127.120.255',
    '2608:3404:1234:2100:0000:0000:0000:11',
    '192.168.1.0',
    '192.168.1.1',
    '1123:3404:1234:2100:0000:0000:0000:11',
    '114.246.18.255',
    '1123:3404:1234:2100:0000:0000:0000:11',
    '61.241.95.0',
    '1123:8642:EFC:1480:0000:0000:0000:1',
    '116.169.105.1',
    '1123:8766:1:D00:0000:0000:0000:1',
];

$ipRanges = [
    '101.127.196.0-101.127.197.255',
    '1123:3404:1234:2100:0000:0000:0000:0000/56',
    '114.246.18.0-114.246.19.255',
    '1123:3404:1234:2000:0000:0000:0000:0000/56',
    '61.241.94.0/23',
    '1123:8642:EFC:1480::/57',
    '61.241.92.0/23',
    '1123:8642:EFC:1400::/57',
    '116.169.104.0/22',
    '1123:8766:1:D00::/56',
    '116.169.104.0/22',
    '1123:8766:1:D00::/56',
    '101.125.212.0/24',
    '1123:8706:0000:5400::/56',
    '1123:8706:0000:5500::/56',
    '101.125.213.0/24',
    '101.125.214.0/24',
    '101.125.215.0/24',
    '116.169.140.0/24',
    '116.169.141.0/24',
    '1123:8766:1:1200::/56',
    '101.148.4.0/22',
    '1123:8740:C4FC:200::/56',
    '119.255.137.0/25',
    '2407:4f00:1:2000::/63',
    '119.255.137.128/25',
    '2407:4f00:1:2002::/63',
    '117.107.160.0/25',
    '240e:604:208:1950::/63',
    '117.107.160.128/25',
    '240e:604:208:1952::/63',
    '183.247.147.192/26',
];

$validator = new IpValidator;
$notInIps = $validator->validateIps($ipArray, $ipRanges);
print_r($notInIps);
所有用户都可以去薅羊毛,192元充值200元话费!先到先得!导航栏话费充值,正规可靠,快充慢充自由选择。
欧阳逸资源站 » php判断数组里面的每个ip是否在给定的另一组ip数组段内

发表评论