我正在使用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中是否存在错误?
答案 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地址表示为三种常规形式 文字字符串:
首选形式是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中描述的情况除外)。
由于某些方法分配了某些样式的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
- 醇>
另一种形式,在交易时有时更方便 具有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
由于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文本表示:
- 醇>
IPv6文本表示的建议书
对IPv6的规范文本表示格式的建议 地址在本节中介绍。这个建议 文档是完全符合[RFC4291]的文档,由。实现 各种操作系统,人性化。建议 在本节中,生成一个系统时应该跟着系统 地址表示为文本,但所有实现必须 接受并能够处理任何合法的[RFC4291]格式。它是 建议人们在拼写时也遵循这些建议 地址。
答案 1 :(得分:-1)
查看源代码,看起来它会将字符串分解为字符,然后对于每个字符串执行一些操作,将位添加到最终结果,然后向左移位4位并继续直到它要么命中:或者结果超过0xFFFF。 (http://www.docjar.com/html/api/sun/net/util/IPAddressUtil.java.html行170到180)。由于字符全为零,显然它永远不会超过0xFFFF,因此它永远不会达到该限制。
我还阅读RFC2373并说前导零是可选的,但它并没有明确限制允许的数量。我说这是一个错误,但(恕我直言)仅适用于迂腐的人。