Inet6Address对无效的IPv6地址有效

时间:2018-06-13 21:21:45

标签: java ipv6

我正在使用java.net.Inet6Address验证输入字符串是否为有效的 IPv6地址

这是我的代码段:

public static boolean isValidIPv6ddress(String address) {
    if (address.isEmpty()) {
        return false;
    }
    try {
        Object res = InetAddress.getByName(address);
        return res instanceof Inet6Address;
    } catch (final UnknownHostException ex) {
        return false;
    }
}

不幸的是,即使以下输入无效,上述方法也会返回true

System.out.println(isValidIPv6ddress("2A00:17C8:50C:0000:0000:0000:0000:00001"));
System.out.println(isValidIPv6ddress("2A00:17C8:50C:0000:0000:00000000000000:0000:00001"));
System.out.println(isValidIPv6ddress("2A00:17C8:50C:00001235:0000:00000000000000:0000:00001"));

API 是否忽略前导?或者API中是否存在错误

2 个答案:

答案 0 :(得分:6)

根据有关IPv6地址有效文本表示的最新RFC,您遇到了错误或IPv6地址文本表示的不良解释。 IPv6地址架构的最新RFC是RFC 4291, IP Version 6 Addressing Architecture。该RFC有Section 2.2. Text Representation of Addresses表示(注意限制是四个十六进制数字):

  

2.2。地址的文本表示

     

将IPv6地址表示为三种常规形式   文字字符串:

     
      
  1. 首选形式是x:x:x:x:x:x:x:x,其中'x'是一个     八个16位地址的四个十六进制数字。     例子:

     ABCD:EF01:2345:6789:ABCD:EF01:2345:6789
    
     2001:DB8:0:0:8:800:200C:417A
    
         

    请注意,没有必要在一个中写入前导零     个别领域,但每个领域必须至少有一个数字     字段(2中描述的情况除外)。

  2.   
  3. 由于某些方法分配了某些样式的IPv6     地址,地址包含长字符串是很常见的     零比特。为了使写入地址包含零     位更容易,可以使用特殊语法来压缩零。     “::”的使用表示一组或多组16位零。     “::”只能在地址中出现一次。 “::”也可以     用于压缩地址中的前导或尾随零。

         

    例如,以下地址

     2001:DB8:0:0:8:800:200C:417A   a unicast address
     FF01:0:0:0:0:0:0:101           a multicast address
     0:0:0:0:0:0:0:1                the loopback address
     0:0:0:0:0:0:0:0                the unspecified address
    
         

    可以表示为

     2001:DB8::8:800:200C:417A      a unicast address
     FF01::101                      a multicast address
     ::1                            the loopback address
     ::                             the unspecified address
    
  4.   
  5. 另一种形式,在交易时有时更方便     具有IPv4和IPv6节点的混合环境     x:x:x:x:x:x:d.d.d.d,其中'x'是十六进制值     这六个高位16位的地址和'd'是     四个低阶8位的十进制值     地址(标准IPv4表示)。例子:

     0:0:0:0:0:0:13.1.68.3
     0:0:0:0:0:FFFF:129.144.52.38
    
         

    或以压缩形式:

     ::13.1.68.3
     ::FFFF:129.144.52.38
    
  6.   

由于RFC 4291要求每个16位字段不超过四个十六进制字符,因此将16位字段中包含四个以上十六进制字符的任何IPv6地址文本表示视为有效是不正确的。 / p>

RFC 4291由RFC 5952, A Recommendation for IPv6 Address Text Representation更新,进一步将16位字段4.1. Handling Leading Zeros中的正确表示限制为无前导零:

  

4.1。处理16位字段中的前导零

     

必须抑制前导零。例如,2001:0db8 :: 0001是   不可接受,必须表示为2001:db8 :: 1。单个16位0000字段必须表示为0。

RFC 5952还需要压缩格式,其中必须将多个连续的16位字段压缩为::

  

4.2。 “:”用法

     

4.2.1。尽可能缩短

     

使用符号“::”必须用于其最大能力。   例如,2001:db8:0:0:0:0:2:1必须缩短为2001:db8 :: 2:1。   同样,2001:db8 :: 0:1是不可接受的,因为符号“::”   本来可以用来产生更短的表示2001:db8 :: 1。

     

4.2.2。处理一个16位0字段

     

符号“::”不得用于缩短一个16位0   领域。例如,表示形式2001:db8:0:1:1:1:1:1是   更正,但2001:db8 :: 1:1:1:1:1不正确。

     

4.2.3。选择“::”

的位置      

如果在“::”的位置有另一种选择,那么   必须缩短最长的连续16位0字段(即,   2001年缩短了连续三个零场的序列:   0:0:1:0:0:0:1)。当连续的16位0字段的长度   是相等的(即2001:db8:0:0:1:0:0:1),第一个零序列   必须缩短比特。例如,2001:db8 :: 1:0:0:1是正确的   表示。

基本上,RFC 5952还要求您接受任何有效的RFC 4291格式,但您只应输出任何RFC 5952格式的IPv6文本表示:

  
      
  1. IPv6文本表示的建议书

         

    对IPv6的规范文本表示格式的建议   地址在本节中介绍。这个建议   文档是完全符合[RFC4291]的文档,由。实现   各种操作系统,人性化。建议   在本节中,生成一个系统时应该跟着系统   地址表示为文本,但所有实现必须   接受并能够处理任何合法的[RFC4291]格式。它是   建议人们在拼写时也遵循这些建议   地址。

  2.   

答案 1 :(得分:-1)

查看源代码,看起来它会将字符串分解为字符,然后对于每个字符串执行一些操作,将位添加到最终结果,然后向左移位4位并继续直到它要么命中:或者结果超过0xFFFF。 (http://www.docjar.com/html/api/sun/net/util/IPAddressUtil.java.html行170到180)。由于字符全为零,显然它永远不会超过0xFFFF,因此它永远不会达到该限制。

我还阅读RFC2373并说前导零是可选的,但它并没有明确限制允许的数量。我说这是一个错误,但(恕我直言)仅适用于迂腐的人。