简体   繁体   中英

How to validate an IPv6 address using a combination of RegEx and code?

I'd like to validate an IPv6 address using an algorithm that emphasizes readability. The ideal solution combines a dead-simple regular expression with source-code.

Using https://blogs.msdn.microsoft.com/oldnewthing/20060522-08/?p=31113 as an example:

function isDottedIPv4(s)
{
  var match = s.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
  return match != null &&
         match[1] <= 255 && match[2] <= 255 &&
         match[3] <= 255 && match[4] <= 255;
}

Notice how Raymond moves the complexity from the regular expression into code. I'd like a solution that does the same for IPv6.

Here is a variant of Brandon's answer :

 /** * @param {String} a String * @return {Boolean} true if the String is a valid IPv6 address; false otherwise */ function isIPv6(value) { // See https://blogs.msdn.microsoft.com/oldnewthing/20060522-08/?p=31113 and // https://4sysops.com/archives/ipv6-tutorial-part-4-ipv6-address-syntax/ const components = value.split(":"); if (components.length < 2 || components.length > 8) return false; if (components[0] !== "" || components[1] !== "") { // Address does not begin with a zero compression ("::") if (!components[0].match(/^[\\da-f]{1,4}/i)) { // Component must contain 1-4 hex characters return false; } } let numberOfZeroCompressions = 0; for (let i = 1; i < components.length; ++i) { if (components[i] === "") { // We're inside a zero compression ("::") ++numberOfZeroCompressions; if (numberOfZeroCompressions > 1) { // Zero compression can only occur once in an address return false; } continue; } if (!components[i].match(/^[\\da-f]{1,4}/i)) { // Component must contain 1-4 hex characters return false; } } return true; } console.log('Expecting true...'); console.log(isIPv6('2001:cdba:0000:0000:0000:0000:3257:9652')); console.log(isIPv6('2001:cdba:0:0:0:0:3257:9652')); console.log(isIPv6('2001:cdba::3257:9652')); console.log(isIPv6('2001:cdba::257:9652')); console.log(isIPv6('2001:DB8:0:2F3B:2AA:FF:FE28:9C5A')); console.log(isIPv6('::0:2F3B:2AA:FF:FE28:9C5A')); console.log('\\n'); console.log('Expecting false...'); console.log(isIPv6(':0:2F3B:2AA:FF:FE28:9C5A')); 

This still may be too complex, but I think it covers most scenarios with IPv6 addresses. I went through something similar recently, it is really hard to replace a huge RegEx for something as complex as IPv6.

 function isIPv6(s) { // Check if there are more then 2 : together (ex. :::) if(/:{3,}/.test(s)) return false; // Check if there are more then 2 :: (ex. ::2001::) if(/::.+::/.test(s)) return false; // Check if there is a single : at the end (requires :: if any) if(/[^:]:$/.test(s)) return false; // Check for leading colon if(/^:(?!:)/.test(s)) return false; // Split all the part to check each var ipv6_parts = s.split(':'); // Make sure there are at lease 2 parts and no more then 8 if(ipv6_parts.length < 2 || ipv6_parts.length > 8) return false; var is_valid = true; // Loop through the parts ipv6_parts.forEach(function(part) { // If the part is not blank (ex. ::) it must have no more than 4 digits if(/^[0-9a-fA-F]{0,4}$/.test(part)) return; // Fail if none of the above match is_valid = false; }); return is_valid; } console.log(isIPv6('2001:cdba:0000:0000:0000:0000:3257:9652')); console.log(isIPv6('2001:cdba:0:0:0:0:3257:9652')); console.log(isIPv6('2001:cdba::3257:9652')); console.log(isIPv6('::2001:cdba:3257:9652')); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM