Javascript 验证IPv4、IPv6和主机名

Javascript 验证IPv4、IPv6和主机名,javascript,regex,validation,ipv6,ipv4,Javascript,Regex,Validation,Ipv6,Ipv4,我正在.net中进行一个项目,该项目可以通过用户输入的IP地址连接到不同的机器。 我正在尝试使用正则表达式验证输入的IP地址。我已经在互联网上搜索了一段时间,但我找不到一个合适的正则表达式 我已经编写了一个小程序来测试正则表达式,请看,(IP地址是随机生成的,如果某些IP地址属于某人,我很抱歉) 你能帮我找到一个可行的解决方案,在客户端验证用户输入吗?!(可以是IPv4、IPv6或主机名,地址中不包括端口) 谢谢。我已经搞定了: 我设法拼凑了一个与IPv6、IPv4和主机名匹配的正则表达式,不幸

我正在.net中进行一个项目,该项目可以通过用户输入的IP地址连接到不同的机器。
我正在尝试使用正则表达式验证输入的IP地址。我已经在互联网上搜索了一段时间,但我找不到一个合适的正则表达式

我已经编写了一个小程序来测试正则表达式,请看,(IP地址是随机生成的,如果某些IP地址属于某人,我很抱歉)

你能帮我找到一个可行的解决方案,在客户端验证用户输入吗?!(可以是IPv4、IPv6或主机名,地址中不包括端口)

谢谢。

我已经搞定了:


我设法拼凑了一个与IPv6、IPv4和主机名匹配的正则表达式,不幸的是,在某些情况下,似乎无效的IP地址就是有效的主机名,但我想这是可以的。
这是正则表达式:)可以找到测试程序

另请参见:


以编程方式构造验证正则表达式 在强大的库
ippaddr.js
[2]中可以找到:

一个全面的JS清单(与旧答案的正则表达式相反:)-以模块化方式编程构造正则表达式

这允许将这些正则表达式的复杂性分解为更容易掌握的基本部分。它还允许您节省代码大小:)

注意:这仅用于验证IP地址版本4和6(不是主机名或其他URI RFC相关内容):

//匹配任意IPv4地址的正则表达式列表,
//存在许多奇怪的符号。
//注意,像0010.0xa5.1.1这样的地址被认为是合法的。
常量ipv4Part='(0?\\d+| 0x[a-f0-9]+);
常量ipv4Regexes={
fourOctet:newregexp(`^${ipv4Part}\\\.${ipv4Part}\.${ipv4Part}\\.${ipv4Part}\\\.${ipv4Part}$`,'i'),
三个八位组:新的RegExp(`^${ipv4Part}\\\.${ipv4Part}\\.${ipv4Part}$`,'i'),
twoOctet:new RegExp(`^${ipv4Part}\\.${ipv4Part}$`i'),
longValue:new RegExp(`^${ipv4Part}$`i')
};
//检查八进制数的正则表达式
const octalRegex=newregexp(`0[0-7]+$`i');
常量hexRegex=newregexp(`0x[a-f0-9]+$`i');
const zoneIndex='%[0-9a-z]{1,}';
//IPv6匹配正则表达式。
//对于IPv6,任务更简单:它足以匹配冒号分隔符
//十六进制IPv6和点十进制IPv4的过渡变体
//结束。
常数ipv6Part='(?:[0-9a-f]+::?)+;
常量ipv6Regexes={
zoneIndex:新的RegExp(zoneIndex,'i'),
'native':新的RegExp(`^(::)?(${ipv6Part})([0-9a-f]+)(::)?(${zoneIndex})$`,'i'),
不推荐的转换:新的RegExp(`^(?::)(${ipv4Part}\\\.${ipv4Part}\.${ipv4Part}\\.${ipv4Part}(${zoneIndex}))$`,'i'),
过渡:新的RegExp(`^((?:${ipv6Part})|(?::)(?:${ipv6Part})${ipv4Part}\\\.${ipv4Part}\\.${ipv4Part}.${ipv4Part}(${zoneIndex})\\\\\''i')
};
简单性成本,需要更多解析逻辑 reg ex部件的整洁是有代价的,所需的解析逻辑更“分叉”:

请在此处检查相应的解析方法:

IPv4.parser

IPv6.parser

充分必要条件 上面结合了解析逻辑的正则表达式通过对任一地址类型的断言的充分条件进行匹配(就像对前面答案的mega正则表达式进行直接匹配一样)

每个地址类型都有许多必要的条件。我们可以使用这些来断言相反的内容(输入不是这两种类型):检查是否缺少
字符是断言地址的一种方法,而不是IP v6。当想要简单地以最佳方式区分(即分类)输入时,这会很有用。在不包含冒号的输入上运行整个IPv6正则表达式将是一项开销

同样值得注意的是,在进行IPv6验证时,上述库还实现了充分条件与必要条件之间的差异(或者特别是为了区分两种地址类型的输入)[1]:

ipaddr.IPv6.isValid=函数(字符串){
//由于始终首先调用IPv6.isValid,因此此快捷方式
//提供了可观的性能增益。
如果(字符串类型=='string'&&string.indexOf(':')===-1){
返回false;
}
试一试{
const addr=this.parser(字符串);
新增此项(添加部件,添加分区ID);
返回true;
}捕获(e){
返回false;
}
};
使用
ipaddr.js
区分v4和v6: [1]
[2]

在node.js中,您可以使用内置模块
net
,该模块具有
net.isIP(ip)
net.isIPv4(ip)
net.isIPv6(ip)


在更新的测试用例中可以找到用于验证IPv4地址的regexp是错误的,
1.2.3.4
应该绝对通过,因为它是有效的IPv4,不是吗?@MikulasDite是的,你是对的,一直在复制粘贴测试用例:我喜欢OP最初指出他在.NET中工作,并且人们发布的所有答案都是JavaScript:D这是保证工作安全的好方法!(我在开玩笑,但我真的认为,如果另一个开发人员来了,想在稍后的时间改变这个验证,他们将有一个艰难的时期,或者必须从头开始。你会考虑使用三个单独的正则表达式吗?一个用于IPv4,一个用于IPv6,另一个用于主机名)。即使是三个带注释的正则表达式也不是最好的解决方案。当使用正则表达式时,它永远不可读。@Yuri这实际上是一个有效的本地url,不是吗?@MikulasDite谢谢!我自己也发现了这一点,w
^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^(?:(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-fA-F]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,1}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,2}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,3}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:[0-9a-fA-F]{1,4})):)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,4}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,5}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,6}(?:(?:[0-9a-fA-F]{1,4})))?::))))$
(^\s*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\s*$)|(^\s*((?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?)*\.?)\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$)


 (
   ^ 
    \s*( //IPv4
        (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
    )\s* 
   $
 )
 |
 (
   ^
    \s*( //Hostname RFC 1123
         (?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?)*\.?
    )\s* 
   $
 )
 |
 (
   ^
    \s*( //IPv6
      (([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))
    )(%.+)?\s*
   $
 )
function getIpVersionNum(addr) {
  try {
    const parse_addr = ipaddr.parse(addr);
    const kind = parse_addr.kind();

    if (kind === 'ipv4') {
      return 4; //IPv4
    } else if (kind === 'ipv6') {
      return 6; //IPv6
    } else {
      throw new Error('unexpected return value');
    }

  // parse() will throw an error when address passes neither validation
  } catch (err) { 
    return 0; //not 4 or 6
  }
}