Google Guava与网络操作相关的类

1.介绍

InternetDomainName是用于解析和操作域名的有用工具。它可以用作验证器、组件提取器以及用作以类型安全的方式传递域名的值类型。

然而,InternetDomainName行为的某些方面可能令人吃惊,并且可能导致调用代码中的错误。本文档解决了这些问题。

2.细节

2.1公共后缀和私有域名

根据相关的RFC规范,可以保证InternetDomainName对象在语法上是有效的,但不能保证它与Internet上的实际可寻址域相对应。如果不对域进行网络查找并尝试与它联系,就不可能做到这一点,对于大多数常见情况而言,这是不可接受的开销。

尽管如此,确定给定域名是否可以代表Internet上的实际域名通常非常有用。为此,我们使用来自公共后缀列表(Public Suffix List (PSL))的数据,该列表由Mozilla Foundation维护。InternetDomainName上有一些方法可以确定给定域名与PSL的关系。用最基本的术语来说,如果domain.hasPublicSuffix()返回true,则该域可能对应于一个真实的Internet地址;否则,几乎可以肯定不会。

在这一点上,我们需要备份并定义一些术语。有四个兴趣条款:

  • 顶级域名(Top-Level Domain (TLD)):没有子域的单标签域,例如comau
  • 注册表后缀:由域名注册机构(例如Verisign for com)控制的域名(例如comco.uk),人们可以在该域名下通过域名注册机构(例如Namecheap)注册子域名。此类域名注册受互联网监管机构(如ICANN)的法律保护。
  • 公共后缀:此类别是注册表后缀的超集,另外还包括不受注册表控制但允许公众注册子域的后缀(例如blogspot.com)。在几种常见情况下,更适合按公共后缀而不是注册表后缀对域进行分类。例如,永远不要在公共后缀上设置cookie。
  • 有效的顶级域:“公共后缀”的已弃用同义词。

在继续之前值得仔细阅读链接中的文章。

造成混淆的一个主要原因是人们说“ TLD”是指“注册后缀”还是“公共后缀”。所有这三个都是独立的概念。例如:

  • com是这三个部分:一个TLD,一个注册后缀和一个公共后缀
  • au是TLD,但不是注册表后缀或公共后缀
  • com.au是注册表后缀和公共后缀,但不是TLD
  • blogspot.com是公共后缀,但既不是注册表后缀也不是TLD
  • squerf不是这三个中的任何一个

这种混淆尤其危险,因为TLD和注册后缀具有明确的正式定义,而公共后缀则没有。最后,一个可靠的消息来源要求PSL维护者将公共后缀添加到列表中。可信来源包括ICANN和国家/地区域管理者,但还包括提供服务的私营公司,这些服务具有(模糊地)定义了公共后缀的特征——独立的子域和超级cookie抑制。例如,PSL中包含许多Google拥有的域(例如blogspot.com)。

回到InternetDomainName,只要我们限制使用hasPublicSuffix()来验证该域是一个合理的Internet域,一切都很好。这种危险来自识别或提取“顶级私有域”的方法。从技术角度来看,顶级私有域只是公共后缀之前最右边的超级域。因此,例如,www.foo.co.uk的后缀为co.uk,顶级私人域为foo.co.uk

正如有关isUnderPublicSuffix()isTopPrivateDomain()topPrivateDomain()的文档所述,这些方法(大多数)唯一可靠的是确定可以在哪里设置Cookie。但是,许多人实际上想做的是从子域中找到“真实”域或“所有者”域。例如,他们希望在mail.google.com中将google.com标识为所有者域。所以他们写

InternetDomainName owner =
    InternetDomainName.from("mail.google.com").topPrivateDomain();

…当然,所有者最终以google.com域为域名。事实上,这种习语(以及类似的习语)在很多时候都起作用。它看起来很直观,“公共后缀下的域”在语义上应等效于“所有者域”。

但这不是问题所在。考虑出现在PSL中的blogspot.com。尽管它具有公共后缀的特征——人们可以在其下注册域名(用于其博客),并且不应该在它上面设置cookie(以防止跨博客cookie恶作剧),它本身是Internet上的一个可寻址域(在撰写本文时,该域恰好重定向到blogger.com,但这很容易更改)。

因此,如果在foo.blogspot.com上使用上述习语,所有者将是相同的域foo.blogspot.com。对于许多常见应用程序来说,这是cookie设置的正确答案,但是对于许多人来说,这显然是令人惊讶的。

对于那些实际上旨在确定从注册表购买的域名的稀有应用程序,正确的抽象不是公共后缀,而是注册表后缀。如果我们更改上面的代码以对注册表后缀使用并行方法:

InternetDomainName owner =
    InternetDomainName.from("foo.blogspot.com").topDomainUnderRegistrySuffix();

…然后我们最终将所有者设置为blogspot.com

这张表格方便的总结了各种后缀类型之间的区别:

InternetDomainName publicSuffix() topPrivateDomain() registrySuffix() topDomainUnderRegistrySuffix()
google.com com google.com com google.com
co.uk co.uk N/A co.uk N/A
www.google.co.uk co.uk google.co.uk co.uk google.co.uk
foo.blogspot.com blogspot.com foo.blogspot.com com blogspot.com
google.invalid N/A N/A N/A N/A

这里的主要经验是:

  • TLD、注册表后缀和公共后缀不是一回事。
  • 公共后缀是由人类定义的,用于严格限制的目的(主要是域验证和超级cookie预防),并且变化是不可预测的。
  • 给定域与公共后缀的关系,该域对Web请求的响应能力以及该域的“所有权”之间没有定义映射。
  • 从ICANN风格的域名注册的角度来看,注册后缀可以帮助你确定域名的“所有权”;但是对于大多数应用程序,此信息不如公共后缀适用。
  • 你可以使用InternetDomainName来确定给定的字符串是否代表Internet上的合理可寻址域,并确定域的哪一部分可能允许设置cookie。
  • 你不能使用InternetDomainName来确定在Internet上是否存在作为可寻址主机的域。

请记住,如果你不听从这个建议,你的代码似乎可以在各种各样的输入上工作…但是失败案例都是等待发生的所有错误,随着PSL更新被合并到InternetDomainName基础代码中,失败案例的集合将发生变化。

本文参考:
InternetDomainNameExplained
guava-tests-net

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章