使用正则表达式验证IPv4和IPv6的PHP函数

23

我需要创建一个函数来处理IPv4和v6地址,同时还需要支持本地IP地址。

我知道有效的IPv4范围是0.0.0.0到255.255.255.255。至于IPv6,我的了解有限,尽管它已经存在一段时间了,但直到今天我才开始了解它。但我希望在保留一定复古感的同时,使得我正在创建的函数具备一定的未来兼容性。我不确定IPv6的有效范围是什么。

总之,我的想法是创建一个函数,大致如下:

function validateIP($ip, $vSix = NULL)
{
    if($vSix !== NULL)
    {
      if(preg_match([regex-to-validate-ipv6], $ip))
      {
        return true;
      }
      else
      {
        return false;
      }
    }

    if(preg_match([regex-to-validate-ipv4], $ip))
    {
      return true;
    }
    else
    {
      return false;
    }
}

我的问题是我不擅长正则表达式,所以我不知道如何编写一个可以验证v4或v6的表达式。此外,对上述函数概念的合理性检查也会很好。

8个回答

57

查看PHP的filter_var函数。它有多个验证器,包括IPv4和IPv6。点击此处了解详情。

$isValid = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
// $isValid can be evaluated as boolean, as it's FALSE if validation fails.

很棒的想法,不知道为什么我没想起来,但是好主意 +1 - chris
1
$isValid 不是 boolean 类型。根据文档:返回过滤后的数据,如果过滤失败则返回 FALSE。 - schnittstabil
@schnittstabil - 年轻的我可能会认为这很迂腐,但实际上这是一个公正的观点。我已经更新了示例,说明它可以转换为布尔值。 - Morgon
@schnittstabil 您是正确的,但他说它可以被评估为布尔值,这并不是不正确的。即使 filter_var 返回过滤后的数据,并且您在条件语句中使用该数据,它仍将被评估为 true。 - SelfTaught
@Dillan 请注意,Morgon已经写道“我已更新示例”... - schnittstabil

24

编辑

请查看 Natxet 在这个回答中的评论,以及 Morgon 的回答获取更好的解决方案。

原始回答

你可以直接使用inet_pton。如果 IP 不是有效的 IPv6 或 IPv4,则返回 false:

function validateIP($ip){
    return inet_pton($ip) !== false;
}

哎呀,我得在php.net上赶紧看看一些新的函数,我甚至都没有意识到。这非常简单而且性感。我刚刚阅读了相关资料后,我想我会选择这个。太棒了! - chris
3
注意!这个函数会抛出一个警告,请不要在函数名前使用@符号来消除它。你应该避免使用这个函数来检查正确的IP地址。正如@marc-pro-campos指出的那样,选项return filter_var($ip, FILTER_VALIDATE_IP));似乎更适合你。 - Natxet

17

尝试

//validates IPv4 and IPv6
$isValid = filter_var($ip, FILTER_VALIDATE_IP);

//validates IPv4
$isValid = filter_var($ip, FILTER_VALIDATE_IP,FILTER_FLAG_IPV4);

//validates IPv6
$isValid = filter_var($ip, FILTER_VALIDATE_IP,FILTER_FLAG_IPV6);

//validates IPv4 and IPv6, excluding reserved and private ranges
$isValid = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE);

http://www.php.net/manual/zh/filter.filters.validate.php


4
除了Morgon和Mark Pro Campos的回答之外,还有以下内容:
function is_valid_ip($ip='', $ip_type=''){

    $isValid=false;

    if($ip_type=='ipv4'){

        //validates IPV4
        $isValid = filter_var($ip, FILTER_VALIDATE_IP,FILTER_FLAG_IPV4);
    }
    elseif($ip_type=='ipv6'){

        //validates IPV6
        $isValid = filter_var($ip, FILTER_VALIDATE_IP,FILTER_FLAG_IPV6);
    }
    else{

        //validates IPV4 and IPV6
        $isValid = filter_var($ip, FILTER_VALIDATE_IP);
    }

    if($isValid == $ip){

        $isValid=true;
    }

    return $isValid;
}

Resources

http://php.net/manual/en/function.filter-var.php


3

尝试:

IPv4

/^((2[0-4]|1\d|[1-9])?\d|25[0-5])(\.(?1)){3}\z/

IPv6

/^(((?=(?>.*?(::))(?!.+\3)))\3?|([\dA-F]{1,4}(\3|:(?!$)|$)|\2))(?4){5}((?4){2}|((2[0-4]|1\d|[1-9])?\d|25[0-5])(\.(?7)){3})\z/i

From: http://home.deds.nl/~aeron/regex/


\z 在结尾有什么作用? - cwd
它的EOL(\z等于$) - Arthur Veselov

2

1
function verify_ip ($ip)
{
    //ipv4
    if(preg_match('#^(\d{1,3}\.){3}\d{1,3}$#', trim($ip))){
        return true;
    }
    //ipv6
    if(preg_match('#^(((?=(?>.*?(::))(?!.+\3)))\3?|([\dA-F]{1,4}(\3|:(?!$)|$)|\2))(?4){5}((?4){2}|((2[0-4]|1\d|[1-9])?\d|25[0-5])(\.(?7)){3})$#i', trim($ip))){
        return true;
    }
    return false;
        
}

0

嗯,我知道这个问题是关于 PHP 的 - 并不是明确关于 Laravel 的。

但为了完整起见,我将发布 PHP Laravel 的解决方案。 要检查有效的 IPv4 或 IPv6 地址,请使用以下代码作为验证规则数组中的值:

// form fieldname to be checked => 'rules ip-separated'
'field1' => 'required|ipv4', // checks for an ipv4 address + field is required
'field2' => 'nullable|ipv4', // checks for an ipv6 address + an empty string is valid as well

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接