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

banq發表於2019-12-12

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如果沒有被解析,是否需要重試?重試多少次,是否一定追求這種高一致性,還是過段時間再試。

 

相關文章