Java正则表达式:用于接受有效的主机名、IPv4或IPv6地址

9

有没有一个好的(最好是经过测试的)正则表达式,只接受有效的DNS主机名、IPv4或IPv6地址?

5个回答

25

我了解您可能被使用正则表达式。然而,如果可能的话,最好避免使用正则表达式来完成此任务,并使用Java库类来进行验证。

如果您想一起进行验证和DNS查找,则InetAddress.getByName(String)是一个很好的选择。它可以一次性处理DNS、IPv4和IPv6,返回一个包含DNS名称(如果提供)和IPv4或IPv6地址的整洁封装的InetAddress实例。

如果您只想进行语法验证,则Apache commons有一些类可以完成这个任务:DomainValidatorInetAddressValidator


遗憾的是,它仅因为主机不存在而抛出异常,而不仅仅是当主机无效时。 - Hakanai
@Trejkaz - 你在谈论什么“它”?你也尝试了另一种方法吗? - Stephen C
@StephenC 对不起,我的意思是特别指出getByName()。对于DomainValidator,您可以从Javadoc中立即看到它通常不起作用,因为它们限制了顶级域名列表,这肯定是人们在添加.eu、.asia等时意识到是个坏主意,并且所有验证都停止工作的地方。 - Hakanai
是的,任何使用静态TLD表的TLD验证器(例如Apache的DomainValidator)都有可能过时。然而,该API确实允许您提供更更新的表格;请参阅updateTLDOverride方法。 - Stephen C

5

Guava推出了一个新类HostSpecifier,它甚至可以验证主机名(如果是主机名)是否以有效的“公共后缀”结尾(例如“.com”,“.co.uk”等),这是基于最新的mozilla公共后缀列表。使用手动编写的正则表达式是不建议尝试的!


1
我不想相信那些快照了“最新”的公共后缀列表的代码,因为几个月后它就不会是最新的了。 - Hakanai

4

正如其他人所说,使用正则表达式实现这个功能是很具有挑战性并且不可取的。但是使用IPAddress Java库可以轻松完成,该库能够解析主机名、IPv4和IPv6地址,而不会触发DNS查找。免责声明:我是该库的项目经理。

示例代码:

check("1.2.3.4");
check("::1");
check("a.b.com");

static void check(String hostStr) {
    HostName host = new HostName(hostStr);
    try {
        host.validate(); // triggers exception for invalid
        if(host.isAddress()) {
            IPAddress address = host.asAddress();
            System.out.println(address.getIPVersion() + " address: " + address);
        } else {
            System.out.println("host name: " + host);
        }
    } catch(HostNameException e) {
        System.out.println(e.getMessage());
    }
}

输出:

IPv4 address: 1.2.3.4
IPv6 address: ::1
host name: a.b.com

如果当前网络无法访问主机名或者被防火墙保护,会发生什么情况呢?会抛出HostNameException异常吗? - andrestascon
不,它不检查主机名是否可达或已使用,它只是检查字符串是否有潜在成为主机名的格式,是否具有有效的主机名格式。它检查它是否为有效的主机名。 - Sean F

1
this post中的代码启发,我创建了下面的验证器方法,似乎非常适合简单的验证需求。通过阅读URI的JavaDoc,我排除了一些误报,如“host:80”和“hostname/page”,但我无法保证是否还有一些误报。请注意,该方法保留HTML标签。
public static boolean isValidHostNameSyntax(String candidateHost) {
    if (candidateHost.contains("/")) {
        return false;
    }
    try {
        // WORKAROUND: add any scheme and port to make the resulting URI valid
        return new URI("my://userinfo@" + candidateHost + ":80").getHost() != null;
    } catch (URISyntaxException e) {
        return false;
    }
}

0

你也可以这样做。比如说:

public boolean isHostnameValid(String hostname) {
    try {
        InetAddress.getAllByName(hostname); // throws an error when the hostnme could not be found, if so, then return false
        return true;
    } catch(Exception exc) {
        return false;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接