PHP ipv6与ipv4工具类

一、PHP 判断IP信息,相关信息的方法仅供大家参考
1.获取ip协议
2.ip转为数值
3.ipv4子网匹配
4.ipv6前缀匹配

二、调用例子

<?php
var_dump(IpUtils::ipToNumeric("20e1::1:2345:6989:abcd"));//获取ipv6的二进制字符信息
var_dump(IpUtils::ipToNumeric("192.168.8.112"));//获取ipv4的数值信息
var_dump(IpUtils::getSubnetMask("192.168.8.112"));//获取ip协议
var_dump(IpUtils::matchCidrIpv4("192.168.8.112","192.168.8.0/24"));//ipv4子网判断
var_dump(IpUtils::matchCidrIPv6("20e1::1:2345:6989:abcd","20e1:0000:0000:0000:0001:2345:6989:abcd/64"));//ipv6前缀判断通过例子  
var_dump(IpUtils::matchCidrIPv6("20e1::1:2345:6989:abcd","20e1:0000:0100:0000:0001:2345:6989:abcd/64"));//ipv6前缀判断不通过例子

三、例如用模拟的数据,返回信息:

string(32) "20e1000000000000000123456989abcd"
string(10) "3232237680"
string(4) "ipv4"
bool(true)
bool(true)
bool(false)

四、调用注意点
matchCidrIpv4与matchCidrIPv6方法的第一个参数一般为客户端ip,第二参数分为两部分用"/"分隔前面是需要匹配的ip,后面的数字表示网络位,ipv4最大32,ipv6最大128。

五、ip工具类实现:

<?php
class IpUtils
{
    /**
     * 获取ip协议
     * @param string $ip IP 地址
     */
    public static function getSubnetMask(string $ip) :string
    {
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            return "ipv4";
        } elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return "ipv6";
        } else {
            throw new \InvalidArgumentException("Invalid IP address");
        }
    }


    /**
     * 将 IP 地址转换为数值。
     * @param string $ip IP 地址
     * @return string|false 转换后的数值,失败时返回 false
     */
    public static function ipToNumeric(string $ip) :string
    {
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            return self::ipv4ToNumeric($ip);
        } elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return self::ipv6ToNumeric($ip);
        } else {
            throw new \InvalidArgumentException("Invalid IP address");
        }
    }

    /**
     * 将 IPv4 地址转换为数值。
     *
     * @param string $ip IPv4 地址
     * @return string 数值
     */
    private static function ipv4ToNumeric(string $ip): string
    {
        return sprintf('%u', ip2long($ip));
    }

    /**
     * 将 IPv6 地址转换为二进制
     * @param string $ip IPv6 地址
     * @return string 数值
     */
    private static function ipv6ToNumeric(string $ip): string
    {
        $ip = inet_pton($ip);
        return bin2hex($ip);
    }

    /**
     * ipv6前缀匹配
     * @param string $ip
     * @param string $cidr
     * @return bool
     */
    public static function matchCidrIPv6(string $ip,string $cidr): bool
    {
        list($matchIp, $prefixLength) = explode('/', $cidr);
        $prefixLength = (int) $prefixLength;
        if ($prefixLength > 128 || $prefixLength < 1) {
            return false;
        }
        // 将 IPv6 地址转换为二进制格式
        $ipBinary = inet_pton($ip);
        $networkBinary = inet_pton($matchIp);
        $maskBinary = str_repeat("\xFF",intval($prefixLength / 8));
        $residue = $prefixLength % 8;
        if ($residue) {
            $num = 0;
            for ($i = 0; $i < 8; $i++) {
                $num <<= 1;
                if ($residue > $i) {
                    $num |= 0b1;
                }
            }
            $maskBinary .= pack("C",$num);
        }
        $maskBinary = str_pad($maskBinary,16,"\x00",STR_PAD_RIGHT);
        return strcmp($ipBinary & $maskBinary,$networkBinary & $maskBinary) === 0;
    }

    /**
     * ipv4 子网匹配
     * @param $ip
     * @param $cidr
     * @return bool
     */
    public static function matchCidrIpv4($ip, $cidr): bool
    {
        list($matchIp, $mask) = explode('/', $cidr);
        if ($mask > 32 || $mask < 1) {
            return false;
        }
        return (ip2long($ip) >> (32 - $mask) == ip2long($matchIp) >> (32 - $mask));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值