【问题标题】:Check Domain Names According to RFC 1035 Standard in Java根据 Java 中的 RFC 1035 标准检查域名
【发布时间】:2019-07-01 12:18:00
【问题描述】:

我正在尝试编写代码来检查域名是否根据 rfc 1035 标准有效。 RFC 1035(https://www.rfc-editor.org/rfc/rfc1035) 标准对域名有以下标准:

<domain> ::= <subdomain> | " "

<subdomain> ::= <label> | <subdomain> "." <label>

<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]

<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>

<let-dig-hyp> ::= <let-dig> | "-"

<let-dig> ::= <letter> | <digit>

<letter> ::= any one of the 52 alphabetic characters A through Z in
upper case and a through z in lower case

<digit> ::= any one of the ten digits 0 through 9

Note that while upper and lower case letters are allowed in domain
names, no significance is attached to the case.  That is, two names with
the same spelling but different case are to be treated as if identical.

The labels must follow the rules for ARPANET host names.  They must
start with a letter, end with a letter or digit, and have as interior
characters only letters, digits, and hyphen.  There are also some
restrictions on the length.  Labels must be 63 characters or less.

我在Java中编写了以下代码sn-p来检查域名是否根据rfc 1035有效。

//DomainUtils.java
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class DomainUtils {

   private static Pattern pDomainNameOnly1;
   private static Pattern pDomainNameOnly2;

   private static final String DOMAIN_NAME_PATTERN_CHK_1 = "^(?![0-9-])[A-Za-z0-9-]{1,63}(?<!-)$";
   private static final String DOMAIN_NAME_PATTERN_CHK_2 = "^((?![0-9-])[A-Za-z0-9-]{1,63}(?<!-)\\.)+(?![0-9-])[A-Za-z0-9-]{1,63}(?<!-)$";

   static {
       pDomainNameOnly1 = Pattern.compile(DOMAIN_NAME_PATTERN_CHK_1);
       pDomainNameOnly2 = Pattern.compile(DOMAIN_NAME_PATTERN_CHK_2);
   }

   public static boolean isValidDomainName(String domainName) {
       return (pDomainNameOnly1.matcher(domainName).find() || pDomainNameOnly2.matcher(domainName).find() || domainName.equals(" "));
   }

}

//Main.java
public class Main{
   public static void main(String[] args){
       boolean valid = DomainUtils.isValidDomainName("a123456789a123456789a123456789a123456789a123456789a1234567891234.ARPA"); //check if domain name is valid or not
       System.out.println("Valid domain name : " + valid);
   }

}

我只是想检查是否有一些有效的方法(除了我写的)来检查域名是否符合 rfc 1035 标准?此外,如果我需要检查我的代码是否适用于 rfc 1035 标准的极端情况,那么我在哪里可以检查。是否有一些现有的库可以用于此检查?

【问题讨论】:

  • 这也取决于你在哪里使用这个检查。 RFC 1035 有各种更新来改变事物。例如,虽然在技术上禁止拥有纯数字 TLD,但实际上现在是不可能的。在stackoverflow.com/a/53875771/6368697查看我的更长回复

标签: regex domain-name rfc1035


【解决方案1】:

试试这个:

^[a-zA-Z]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*$

可以在demo中显示

为了构造这个表达式,我们首先使用标签组件(a-zA-Z 集合中的单个字符,后跟(可选)集合a-zA-Z0-9- 中的一系列字符,并以非- 结尾(连字符允许在内部,但不允许在标签的开头或结尾)导致

[a-zA-Z]([a-zA-Z0-9-]*[a-zA-Z0-9])?

这个表达式按照以下模式重复:

A(\.A)*

表示A 的序列,后跟任意数量(甚至0)的点序列,后跟A 的另一个实例。

通过将上述正则替换为 A 的位置,我们得到了最终的正则表达式。锚点消除了字符串开头/结尾的任何其他周围字符串。

要检查标签最多只能包含 63 个字符,您可以这样做

[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?

但要小心,因为这个正则表达式会编译成一个非常大的表自动机(一个有许多状态的自动机),所以如果空间不足,你最好放松一下。

【讨论】:

  • 这并没有考虑到所有情况,但这取决于 OP 究竟想要什么(RFC 1035 不再是关于域名语法的最新参考)。例如,任何标签的第三个和第四个字符不能是--,除非它是xn-- 形式的IDN,然后只有xn 可以用作前缀,没有别的。
  • 恐怕xn-- 前缀(不仅是最后两个连字符)是 IANA 用于实现可扩展性的一种方式。允许使用双破折号迫使更改基本的 DNS 语法。我不知道禁止将-- 置于该位置用于与IDN 不同的用途。无论如何,您是否有域名语法的实际参考 RFC。我知道,最初允许 DNS 名称以数字开头(即使与 IPV4 地址的文本描述冲突)
  • 请参阅我的回答,回答一个问题,该问题应该为您提供有关语法和格式以及多年来变化的指导:stackoverflow.com/a/53875771/6368697
  • 关于连字符,请参阅 ICANN IDN 实施指南icann.org/en/system/files/files/idn-guidelines-10may18-en.pdf 第 4 点:“除非是有效的 A 标签,否则不得注册在第三和第四位置都包含连字符的标签,但有保留用于过渡动作。在第三个和第四个位置都带有连字符的标签被明确保留以指示编码方案,其中 IDNA 只是一个实例。"
猜你喜欢
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 2012-09-23
  • 1970-01-01
  • 2015-05-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多