【问题标题】:IPv6 validationIPv6 验证
【发布时间】:2011-08-23 05:18:43
【问题描述】:

我使用IPAddressUtil.isIPv6LiteralAddress (ipAddress)方法来验证IPv6,但是这种方法对于IPV6的ipv6地址/前缀长度格式(格式在RFC 4291第2.3节中提到)失败。

有人知道任何验证“ipv6-address/prefix-length”格式的验证器吗?

IPV6 的法律代表

  1. ABCD:EF01:2345:6789:ABCD:EF01:2345:6789
  2. 2001:DB8:0:0:8:800:200C:417A
  3. FF01:0:0:0:0:0:0:101
  4. 0:0:0:0:0:0:0:1
  5. 0:0:0:0:0:0:0:0
  6. 2001:DB8::8:800:200C:417A
  7. FF01::101
  8. ::1
  9. ::
  10. 0:0:0:0:0:0:13.1.68.3
  11. 0:0:0:0:0:FFFF:129.144.52.38
  12. ::13.1.68.3
  13. FFFF:129.144.52.38
  14. 2001:0DB8:0000:CD30:0000:0000:0000:0000/60
  15. 2001:0DB8::CD30:0:0:0:0/60
  16. 2001:0DB8:0:CD30::/60

不是 IPV6 的法律代表

  1. 2001:0DB8:0:CD3/60
  2. 2001:0DB8::CD30/60
  3. 2001:0DB8::CD3/60

【问题讨论】:

  • 您能举个例子说明您要匹配的内容吗?
  • 好的,请看下面的ip地址,2001:0DB8:0000:CD30:0000:0000:0000:0000/60
  • 该格式适用于地址前缀,而不是地址。
  • @Tony,您找到解决方案了吗?我也在寻找解析 IPv6 前缀地址。

标签: java regex parsing validation ipv6


【解决方案1】:

看看这是否有效:

try {
    if (subjectString.matches(
        "(?ix)\\A(?:                                                  # Anchor address\n" +
        " (?:  # Mixed\n" +
        "  (?:[A-F0-9]{1,4}:){6}                                # Non-compressed\n" +
        " |(?=(?:[A-F0-9]{0,4}:){2,6}                           # Compressed with 2 to 6 colons\n" +
        "     (?:[0-9]{1,3}\\.){3}[0-9]{1,3}                     #    and 4 bytes\n" +
        "     \\z)                                               #    and anchored\n" +
        "  (([0-9A-F]{1,4}:){1,5}|:)((:[0-9A-F]{1,4}){1,5}:|:)  #    and at most 1 double colon\n" +
        " |::(?:[A-F0-9]{1,4}:){5}                              # Compressed with 7 colons and 5 numbers\n" +
        " )\n" +
        " (?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}  # 255.255.255.\n" +
        " (?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])           # 255\n" +
        "|     # Standard\n" +
        " (?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}                    # Standard\n" +
        "|     # Compressed\n" +
        " (?=(?:[A-F0-9]{0,4}:){0,7}[A-F0-9]{0,4}               # Compressed with at most 7 colons\n" +
        "    \\z)                                                #    and anchored\n" +
        " (([0-9A-F]{1,4}:){1,7}|:)((:[0-9A-F]{1,4}){1,7}|:)    #    and at most 1 double colon\n" +
        "|(?:[A-F0-9]{1,4}:){7}:|:(:[A-F0-9]{1,4}){7}           # Compressed with 8 colons\n" +
        ")/[A-F0-9]{0,4}\\z                                                    # Anchor address")) 
        {
        // String matched entirely
    } else {
        // Match attempt failed
    } 
} catch (PatternSyntaxException ex) {
    // Syntax error in the regular expression
}

大约一年前,我购买了一个非常有用的程序 RegexMagic,用于我计划使用的一些复杂的正则表达式。

这应该是Java,所以它应该编译,我假设/60可以在0000和FFFF之间你可以修改最后一部分。

/[A-F0-9]{0,4} 是我添加到正则表达式中以匹配您的示例。

【讨论】:

  • 上面的正则表达式可能工作......但这太庞大了,我无法想象有人(包括原作者)知道如何一年剖析它之后。我不会链接这么多|,而是将它分解成一堆“else if”语句,这至少有助于更容易调试
  • 对于 IPv4,它是 0-32。对于 IPv6,它是 0-128。 32 或 128 将是单个地址,31 或 127 将是两个地址,30 或 126 将是四个地址,等等。
【解决方案2】:

可以使用 Guava 库,具体使用 com.google.common.net.InetAddresses 类,调用 isInetAddress()


isInetAddress

public static boolean isInetAddress(String ipString)

如果提供的字符串是有效的 IP 字符串文字,则返回 true,否则返回 false。

参数ipString - 要评估为 IP 字符串文字的字符串

返回true 如果参数是有效的 IP 字符串文字

【讨论】:

  • 它不适用于 IPv6 前缀。仅适用于 IPv6 地址。 @broc.seib
【解决方案3】:

严格来说,第2.3节没有描述地址表示,而是地址前缀的表示(甚至“全长”前缀也不等同于地址)。

IPv6 地址前缀是 由符号表示: ipv6 地址/前缀长度 在哪里 ipv6-address 是列出的任何符号中的 IPv6 地址 在第 2.2 节中。

这意味着如果您需要验证地址,您可以放心地忽略此格式。

【讨论】:

    【解决方案4】:

    我的想法是把它分成两部分,前缀地址和前缀len。

    1.验证前缀地址使用一些正则表达式来验证 IPv6 地址
    2.验证必须是整数的前缀 len
    3.前缀地址只能有':'小于prefix len divided by 16的结果
    4。其他逻辑也必须考虑,将 TODO 留在这里,对不起:(

      private int validateIPv6AddrWithPrefix(String address) {
            int occurCount = 0;
            for(char c : address) {
                if(c=='/'){
                    occurCount++;
                }
            }
            if(occurCount != 1){
             //not good, to much / character
                return -1;
            }
            /* 2nd element should be an integer */
            String[] ss = pool.getAddress().split("/");
            Integer prefixLen = null;
            try{
                prefixLen = Integer.valueOf(ss[1]);
                        // TODO validate the prefix range(1, 128)
    
            }catch(NumberFormatException e) {
                /* not a Integer */
                return -1;
            }
            /* 1st element should be ipv6 address */
            if(!IPaddrUtilities.isIPv6Address(ss[0])) {
                return -1;
            }
            /* validate ':' character logic */
            occurCount = 0;
            for(char c : ss[0].toCharArray()){
                if(c==':') {
                    occurCount++;
                }
            }
            if(occurCount >= prefixLen/16) {
                // to much ':' character
                return -1;
            }
            return 0;
        }
    

    【讨论】:

    • 您能否发布完整的 Java 解决方案以进行 IPV6 验证?
    【解决方案5】:

    我在java中尝试过下面的正则表达式,它适用于IPV4和IPV6

    public class Utilities {
    private static Pattern VALID_IPV4_PATTERN = null;
    private static Pattern VALID_IPV6_PATTERN = null;
    private static final String ipv4Pattern = "(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])";
    private static final String ipv6Pattern = "([0-9a-f]{1,4}:){7}([0-9a-f]){1,4}";
    
    static {
    try {
      VALID_IPV4_PATTERN = Pattern.compile(ipv4Pattern, Pattern.CASE_INSENSITIVE);
      VALID_IPV6_PATTERN = Pattern.compile(ipv6Pattern, Pattern.CASE_INSENSITIVE);
       } catch (PatternSyntaxException e) {
      //logger.severe("Unable to compile pattern", e);
     }
    }
    
     /**
     * Determine if the given string is a valid IPv4 or IPv6 address.  This method
     * uses pattern matching to see if the given string could be a valid IP address.
     *
     * @param ipAddress A string that is to be examined to verify whether or not
     * it could be a valid IP address.
     * @return <code>true</code> if the string is a value that is a valid IP address,
     *  <code>false</code> otherwise.
     */
     public static boolean isIpAddress(String ipAddress) {
    
    Matcher m1 = Utilities.VALID_IPV4_PATTERN.matcher(ipAddress);
    if (m1.matches()) {
      return true;
    }
    Matcher m2 = Utilities.VALID_IPV6_PATTERN.matcher(ipAddress);
    return m2.matches();
      }
    
    
    }
    

    【讨论】:

    • 这似乎并没有尝试处理 :: 版本和以 IPv4 地址结尾的版本。
    • 对 IPV6 模式的轻微修改:Pattern VALID_IPV6_PATTERN = Pattern.compile("([0-9a-f]{1,4}:{1,2}){4,7}( [0-9a-f]){1,4}", java.util.regex.Pattern.CASE_INSENSITIVE);
    【解决方案6】:

    The IPAddress Java library 支持以多态方式解析 IPv4 和 IPv6 CIDR 子网(即地址/前缀格式)。免责声明:我是项目经理。

    以下方法是验证的示例代码:

    static void parse(String str) {
        IPAddressString addrString = new IPAddressString(str);
        try {
             IPAddress addr = addrString.toAddress();
             IPAddress hostAddr = addrString.toHostAddress();
             Integer prefix = addr.getNetworkPrefixLength();
             if(prefix == null) {
                 System.out.println(addr + " has no prefix length"); 
             } else {
                 System.out.println(addr + " has host address " + hostAddr + " and prefix length " + prefix);
             }
        } catch(AddressStringException e) {
            System.out.println(addrString + " is invalid: " + e.getMessage());
        }
    }
    

    使用问题中提供的示例,上述方法的输出为:

    abcd:ef01:2345:6789:abcd:ef01:2345:6789 has no prefix length
    2001:db8::8:800:200c:417a has no prefix length
    ff01::101 has no prefix length
    ::1 has no prefix length
    :: has no prefix length
    2001:db8::8:800:200c:417a has no prefix length
    ff01::101 has no prefix length
    ::1 has no prefix length
    :: has no prefix length
    ::d01:4403 has no prefix length
    ::ffff:8190:3426 has no prefix length
    ::d01:4403 has no prefix length
    FFFF:129.144.52.38 is invalid: FFFF:129.144.52.38 IP Address error: address has too few segments
    2001:db8:0:cd30::/60 has host address 2001:db8:0:cd30:: and prefix length 60
    2001:db8:0:cd30::/60 has host address 2001:db8:0:cd30:: and prefix length 60
    2001:db8:0:cd30::/60 has host address 2001:db8:0:cd30:: and prefix length 60
    2001:0DB8:0:CD3/60 is invalid: 2001:0DB8:0:CD3/60 IP Address error: address has too few segments
    2001:db8::cd30/60 has host address 2001:db8::cd30 and prefix length 60
    2001:db8::cd3/60 has host address 2001:db8::cd3 and prefix length 60
    

    如您所见,关于 FFFF:129.144.52.38 有效且 2001:db8::cd30/60 和 2001:db8::cd3/60 无效的问题不正确。如果是 ::FFFF:129.144.52.38

    ,则第一个将是有效的

    【讨论】:

      猜你喜欢
      • 2013-12-09
      • 2012-08-28
      • 2014-11-01
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多