PHP 判断 IPv4 地址是否在某个 IP 段内的方法

小助手读文章 00:00 / 00:00

温馨提示:
本文所述内容具有依赖性,可能因软硬条件不同而与预期有所差异,故请以实际为准,仅供参考。

在做安全访问限制时,有时候我们需要做 IP 黑名单或者白名单,为减小策略长度,提高效率,比较常见的用法就是对该 IP 段内的所有 IP 进行允许或者限制,由此带来一个问题,就是我们如何判断某个 IP 是否属于某个 IP 段内。

判断一个 IP 是否属于某一个 IP 段,思路就是将 varchar类型的 IP 转换成 int 类型的数值,然后进行比较。在 PHP 中内置了 ip 和数值的互换的函数:ip2long($ip_addr)long2ip($long)

ip2long($ip_addr)中若 $ip_addr 不是有效的 IP 地址,则会返回 false,若是有效的 IP 地址,则会将其转换为有符号 long 类型,而有些时候 IP 地址转换后可能会超出有符号的 long 长度,这样会导致出现负数。

long 类型是 4 个字节的,其有符号范围是:2147483647 ~ -2147483648,无符号的范围是:4294967295 ~ 0

最大的 IP4 地址是:255.255.255.255,对应的数值是:4294967295,所以可以将其转成无符号的数值。2147483647 数值对应的 IP 为:127.255.255.255,所以 IP 地址在 0.0.0.0127.255.255.255 范围内的不会出现负数,而在 128.0.0.0 ~ 255.255.255.255 范围内的会出现负数情况。

以下代码给出了一个完整、正确的判断指定 IP 是否属于某 IP 段内的小例子:

$start_ip = "42.236.184.1";
$end_ip   = "42.236.184.255";
$ip = "42.236.184.128";
function check_ip($ip,$start_ip,$end_ip)
{
    $ip = get_ip2long($ip);
    $start_ip = get_ip2long($start_ip);
    $end_ip = get_ip2long($end_ip);
    if($ip >= $start_ip && $ip <= $end_ip)
    {
        return true;
    }
    return false;
}
function get_ip2long($ip)
{
    return bindec(decbin(ip2long($ip)));
//    方法二:return sprintf('%u',ip2long($ip));    //    %u:不包含正负号的十进制数
// decbin() 十进制转二进制。
// bindec() 二进制转十进制。函数将一个二进制数转换成 integer。可转换的最大的数为 31 位 1 或者说十进制的 2147483647。PHP 4.1.0 开始,该函数可以处理大数值,这种情况下,它会返回 float 类型。
}

check_ip($ip,$start_ip,$end_ip);

其实本文还有一个应用场景,就是通常存储在数据库中的 IP 地址都是 varchar 类型的,而如果采用 INT 类型来保存 IP ,则可以对数据库起到优化的作用。


参考文章:

1、《PHP 判断某个 IP4 是否属于某一个 IP 段(ip2long())


ArmxMod for Typecho
个性化、自适应、功能强大的响应式主题

推广

 继续浏览关于 php运维经验开发方法ipv4 的文章

 本文最后更新于 2019/08/30 12:20:00,可能因经年累月而与现状有所差异

 引用转载请注明: VirCloud's Blog > 运维 > PHP 判断 IPv4 地址是否在某个 IP 段内的方法