Java的URL.equals()方法竟然执行DNS解析| 黑客新闻

19-12-12 banq

DNS解析是一个非常耗时且容易失败且容易受到攻击的过程,在Java的URL的equslas()方法竟然执行DNS解析,这个方法主要是判断两个URL是否等同,主要依据:

1. 如果两个URL对象具有相同的协议,引用等效的主机,在主机上具有相同的端口号以及相同的文件和文件片段,则它们是相等的。

2. 如果两个主机名都可以解析为相同的IP地址,则认为这两个主机等效。

这在HN引起很多讨论,有人奇怪为什么要URL解决任何问题?URL只是一个字符串,这应该只是在进行字符串比较。URL对象的所有部分都是字符串或整数,因此在最坏的情况下,它们应该只是单独比较所有这些内容,而不是解析域并比较IP地址。那根本没有道理。

这可能与当时名称解析在Sun内部的工作方式有关。

doppio.eng.sun.com

在工程(“ eng.sun.com”)域内,它简称为“ doppio”,在Sun内部的其他域中,则简称为“ doppio.eng”。在Sun内部使用FQDN引用Sun内部的其他主机是非常罕见的。因此,以下URL都引用相同的资源:

http://doppio/foo.html

http://doppio.eng/foo.html

http://doppio.eng.sun.com/foo.html

URL.equals()对于以上两个URL中的任何一个都报告为true是一种合理的观点。(但是,这并不意味着我认为这是一个好主意。)

从某种意义上说,Java和Windows一样好,因为它的标准库和API集非常稳定,并且支持许多旧版软件。鉴于将近18年前在JDK 1.4中引入了URI类,因此我现在怀疑在新代码中是否确实需要URL类。尽管有很多依赖关系,所以URL可能会永远保留在核心库中,但是URI代表URL的超集,具有equals / hashCode的合理实现,并且足以满足大多数用途。

不过,URL类还是用于建立与资源的实际连接。

这在equals定义的这种行为与HTTP中的虚拟主机不一致。不过,此功能于1995年引入,那是还没有虚拟主机。

如果我的DNS解析器使用轮询并在每个请求上返回不同的IP怎么办?因为现在很多大的域名都有动态解析,每次DNS解析获得的IP不同。

这个功能看起来像是有太多时间的开发人员决定添加一些巨大的副作用。

这是很有趣,如果“ url..com”和“ url2.com”两个不同域名都解析为相同的IP,则它们在功能上是相同的。这就像比较两个字符串,它们的变量名不同,但解析为内存中的相同空间。这也意味着,如果一个URL发生更改,则有时它们可​​以相等,而其他URL则不相等。

equals()和hashCode()可能是Java的最弱点之一。不同的用例将需要不同的等同定义。如果对象具有相同的标识,是否相等?如果它们具有相同的数据?如果他们决心解决同一件事?使其简单地实现起来很容易,但是问题是缺少标准的库支持,无法为map和集合提供自定义的哈希和相等函数。(banq注:这看来是一个业务DDD的问题)

banq:这其实是一个分布式问题,有CAP定理在其中权衡,URL如果没有被解析,是否需要重试?重试多少次,是否一定追求这种高一致性,还是过段时间再试。

 

                   

1
猜你喜欢