新gTLDS的apache commons-validator替代方案

时间:2014-11-25 16:54:37

标签: java apache validation

我需要验证电子邮件和域名。我只需要正式验证,不需要whois或其他形式的域查找。

目前我正在使用apache' s commons-validator v1.4.0

不幸的是,我的客户使用新的gTLD,例如DomainValidator类尚不支持的.bike或.productions。 有关详细信息,请参阅Apache's Jira issue

我可以轻松地在Maven POM中包含任何合理的替代方案吗?

5 个答案:

答案 0 :(得分:7)

如果您不关心国际化地址,可以更改地址的最后部分,并继续使用Apache公共地址。

此方法基于以下事实:无论TLD是什么,整个域名的有效性等同于域名替换为com的相同域名的有效性。例如:

  • abc.def.com有效。同样,abc.def.nameabc.def.xx--kput3iabc.def.uk也有效。
  • ab,de.com无效。同样,ab,de.nameab,de.xx-kput3iab,de.uk无效。

所以不要打电话

return EmailValidator.getInstance().isValid(userEmail);

你可以打电话

if ( userEmail == null ) {
    return false;
}
return EmailValidator.getInstance().isValid(userEmail.trim().replaceFirst("\\.\\p{Alpha}[\\p{Alnum}-]*\\p{Alnum}$", ".com"));

说明

  • 正则表达式"\\.\\p{Alpha}[\\p{Alnum}-]*\\p{Alnum}$"检查TLD部分:它位于字符串的末尾(由于$),它以点开头,不包含其他点,并且它符合标准:以ASCII Alpha字符开头,后跟零个或多个字母数字或破折号,并以字母数字字符结尾。
  • 我正在使用trim()因为到目前为止,如果您使用EmailValidator,它会在地址之前和之后允许空格。删除空格只会使更换TLD变得更容易,就地址的有效性而言,这并不重要。
  • 如果字符串末尾没有有效的TLD,String.replaceFirst()将按原样返回。它仍然有效,因为x@[n.n.n.n]格式的电子邮件地址n.n.n.n.是有效的IP地址。所以基本上,如果您没有找到顶级域名,请让EmailValidator自行决定有效性问题。
  • 当然,如果TLD不是IANA认可的TLD,则此验证不会告诉您。像david@galaxy.hoopie-frood这样的电子邮件将被视为合法邮件,但IANA尚未拥有该顶级域名。

检查域名类似,没有trim()部分:

if (userDomain == null ) {
   return false;
}
return DomainValidator.getInstance().isValid(userDomain.replaceFirst("\\.\\p{Alpha}[\\p{Alnum}-]*\\p{Alnum}$"));

我也尝试过JavaMail的电子邮件地址验证,但我不是很喜欢它:它允许完全无效的域名,例如net-name.net-(以破折号结尾)或IP地址(不允许使用没有方括号的电子邮件),它只适用于电子邮件地址,而不适用于域名。

国际

如果您需要检查国际化域名和电子邮件,则会有所不同。检查国际化域名(例如元気。テスト)很容易。您需要做的就是使用java.net.IDN.toASCII()将它们转换为ASCII(我的示例域产生xn--z4qx76d.xn--zckzah - 这是一个有效的TLD),然后按照我上面的说法进行操作。

国际化的电子邮件是另一回事。如果本地部分是ASCII,则可以将域部分转换为ASCII。如果必须显示电子邮件地址,则需要使用Unicode版本,如果必须发送电子邮件,则使用ASCII版本。

但最近也为国际化本地部分引入了一个标准,它也允许发送到域名的unicode版本而不首先将其转换为ASCII。无论您是否想要支持,都需要一些思考,因为目前没有多少邮件服务器和邮件传输代理支持它。

答案 1 :(得分:1)

DomainValidator复制了实施,并将TOP_LABEL_REGEX表达式替换为"\\p{Alpha}[\\p{Alnum}-]*\\p{Alpha}"

此外,我删除了针对已批准gTLD的硬编码列表的验证。这基本上是非常弱的,因为它不会对实际域进行验证。但我认为这已经足够好了(抓住与XN--YGBI2AMMX类似的通用顶级域名)。

查看已批准的gTLD完整列表here

// Copied from org.apache.commons.validator.routines.DomainValidator
private static final String DOMAIN_LABEL_REGEX = "\\p{Alnum}(?>[\\p{Alnum}-]*\\p{Alnum})*";
// Changed to include new gTLD - http://data.iana.org/TLD/tlds-alpha-by-domain.txt
private static final String TOP_LABEL_REGEX = "\\p{Alpha}[\\p{Alnum}-]*\\p{Alpha}";
// Copied from org.apache.commons.validator.routines.DomainValidator
private static final String DOMAIN_NAME_REGEX = "^(?:" + DOMAIN_LABEL_REGEX + "\\.)+" + "(" + TOP_LABEL_REGEX + ")$";
private static final RegexValidator domainRegex = new RegexValidator(DOMAIN_NAME_REGEX);

private static final EmailValidator EMAIL_VALIDATOR = new EmailValidator();

public static boolean isValidDomain(String domain) {
    String[] groups = domainRegex.match(domain);
    return groups != null && groups.length > 0;
}

答案 2 :(得分:0)

在这种情况下我经常做的是检查相关库的源代码(它的开源是否记得?),修改它以满足我的要求,然后将补丁提供给项目。

您的用例肯定听起来像是一个有用的贡献。

答案 3 :(得分:0)

我让你成为public suffix list Java API。方法PublicSuffixList.getRegistrableDomain()可用于域验证:

PublicSuffixListFactory factory = new PublicSuffixListFactory();
PublicSuffixList suffixList = factory.build();

assertNull(suffixList.getRegistrableDomain("galaxy.hoopie-frood"));
assertNotNull(suffixList.getRegistrableDomain("example.bike"));

答案 4 :(得分:0)

虽然DomainValidator缺少一些新的TLD,但对我而言,最好的解决方案是更新TLD。

DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_PLUS, new String[]{"someTLD"});

然后启动EmailValidator实例

EmailValidator.getInstance(false, true)