Java恶意序列化背后的历史和动机
與Java的序列化機制有關的問題已廣為人知。 有效的Java 1st Edition (第10章)和有效的Java 2nd Edition (第11章)的整個最后一章都專門討論Java的序列化主題。 Effective Java 3rd Edition (第12章)的最后一章仍致力于序列化,但是其中包括一個新項目(Item 85) ,該項目甚至進一步強調了與Java序列化有關的兩個斷言 :
- “ 避免序列化攻擊的最佳方法是永遠不要反序列化任何東西。 “
- “ 您沒有理由在您編寫的任何新系統中使用Java序列化。 “
在最近發布的文檔“ 邁向更好的序列化 ”中,Brian Goetz“探討了改善Java平臺中序列化的可能方向。” 盡管本文檔的主要目的是為Java序列化提出潛在的新方向,但它只是“一個探索性文檔,并不構成任何特定功能的計劃。” 這意味著對于Java序列化可能采取的方向來說,這是一個有趣的讀物,但是閱讀本文檔對于Java序列化的總結(當前存在的意義以及我們如何到達此地)具有重要的價值。 這是我其余文章的主題,在本文中我將參考并總結“ 邁向更好的序列化 ”的各個部分,這些部分使我感覺最清楚地闡明了Java序列化機制的當前問題以及我們為什么遇到這些問題。
Goetz在Java序列化的“悖論”中引人注目的段落打開了文檔的“動機”部分:
Java的序列化工具有點自相矛盾。 一方面,這可能對Java的成功至關重要-沒有它,Java可能不會占據統治地位,因為序列化實現了透明的遠程處理,進而實現了Java EE的成功。 另一方面,Java的序列化幾乎使每一個錯誤都可以想象到,并給庫維護人員,語言開發人員和用戶帶來持續的稅負(以維護成本,安全風險和緩慢的發展為形式)。
Goetz文檔“動機”部分的另一段區分了序列化的一般概念和Java當前的序列化機制的特定設計 :
需要明確的是,
序列化的概念 ; 將對象轉換為可以輕松跨JVM傳輸并在另一側重構的形式的能力是一個非常合理的想法。 問題出在
Java中的序列化設計 ,以及它如何適合(或更確切地說,不適合)對象模型。
Goetz指出“ Java的序列化(錯誤)是多方面的”,他概述了Java序列化設計所犯的“部分罪過”。 我強烈建議閱讀原始文檔 ,以獲取對這些“罪過”的簡明和說明性描述,此處僅作總結。
- “偽裝成圖書館的功能,但不是。”
- “序列化偽裝成一個庫功能。
- “假裝是靜態類型的功能,但不是。”
- “可序列化性是對象的動態類型的函數,而不是其靜態類型的函數。”
- “編譯器無濟于事”指出“編寫可序列化類時可能犯的各種錯誤”
- “魔術方法和字段”是“不影響序列化行為的任何基類或接口指定的”
- “絕對必要。”
- “緊密結合到編碼。”
- “不幸的流格式”,“既不緊湊,也不高效,也不可讀”。
Goetz還概述了這些Java序列化設計決策的后果(有關每個“嚴重問題”的更多背景,請參閱原始文檔 ):
- “使圖書館維護者癱瘓。”
- “庫設計人員在發布可序列化的類之前必須非常仔細地考慮-因為這樣做可能使您維護與曾經被序列化的所有實例的兼容性。”
“嘲笑封裝。”
- “串行化是您內部狀態的無形但公共的構造函數,以及一組無形但公共的訪問器。”
在Goetz的“ 邁向更好的序列化 ”文檔中,我最喜歡的部分可能是“潛在的錯誤”部分,因為Goetz在本部分中概述的項目是我編寫,閱讀和使用的其他Java代碼中錯誤的常見原因。 換句話說,盡管Goetz特別討論了這些設計決策如何導致Java的序列化機制出現問題,但我(毫無疑問)發現這些通用設計決策也導致了其他領域的問題。
Goetz用以下語句打開“潛在的錯誤”部分:“上面列出的許多設計錯誤都來自一個共同的來源-選擇通過“魔術”實現序列化,而不是將解構和重建放在對象的第一位。模型本身。” 我發現由其他開發人員甚至我自己編寫的“魔術”代碼在以后常常令人困惑且難以推理。 我已經明確地意識到,通常最好使用簡潔明了的代碼。
格茨補充說:“更糟糕的是,魔術盡了最大努力,以使讀者看不見。” 當我們第一次實現隱形的“魔術”設計時,它們通常看起來很聰明,但是當他們突然需要對基礎魔術的可見性時,使必須閱讀,維護和更改代碼的開發人員感到非常痛苦。
Goetz引用了Edsger W.Dijkstra的話,并寫道:“序列化(目前已實現)與減少程序文本和其計算效果之間的差距完全相反; 我們可能會錯誤地假設我們的對象總是由類中編寫的構造函數初始化而得到原諒,但我們不必如此。
Goetz在“底層錯誤”部分的結尾處開始了一段,“序列化除了試圖變得不可見之外,還嘗試做太多事情 。 盡管Goetz專門針對Java的序列化編寫了當前的“序列化程序 (而不是僅僅序列化數據 )”的文章,但從更廣泛的意義上講,我已經無數次地看到了這個問題。 對于我們的開發人員來說,設計和實現可以執行某些我們認為可能對某人有用的小功能的代碼很誘人,即使絕大多數(或什至所有當前已知的)用戶和用例只需要一個簡單的子集即可。功能。
鑒于“ 邁向更好的序列化 ”的目標是“探索改善Java平臺中序列化的可能方向”,因此文檔中涉及到可能影響Java未來序列化機制的設計甚至實現細節的重要細節也就不足為奇了。 此外, Project Amber郵件列表( amber-dev和amber-spec-experts )也對Java序列化的未來發展方向進行了重要討論。 但是,本文的目的不是看Java序列化的未來,而是著眼于本文檔如何很好地總結了Java當前的序列化機制及其歷史。
盡管前面提到的Project Amber郵件列表中的消息集中在Java的序列化機制的潛在未來上,但是這些帖子中有關Java當前序列化的一些有趣的評論增加了Goetz在“ 邁向更好的序列化 ”中所總結的內容。 以下是一些最有趣的內容:
- Goetz在宣布“ 邁向更好的序列化 ” 的帖子中指出,該提案“從根本上解決了序列化的風險”,并“將對象序列化帶到了光明的地方,為了確保安全性,必須要這樣做。”
- Brian Goetz的帖子通過暗示重申了當今Java序列化問題的很大一部分是在不調用構造函數的情況下構造對象:“我們的主要安全目標[是允許]反序列化[通過]構造函數進行。”
- 斯圖爾特·馬克斯(Stuart Marks)的帖子指出:“提案中關于便利性的推理路線并不是說便利本身就是邪惡的,而是為了追求便利,原始設計采用了語言學機制來實現這一目的。 這削弱了Java平臺的某些基礎,并直接導致了多個錯誤和安全漏洞,其中一些是我個人修復的。”
- Marks概述了一些由于序列化相關的設計決策而導致JDK中細微錯誤的特定示例。
- Kevin Bourrillion的帖子指出:“ Java的序列化實現很長一段時間以來一直是一個巨大的傷口”,并補充說“支持其他有線格式的每個框架始終必須從頭開始。”
我強烈建議任何對Java序列化感興趣的人閱讀“ 邁向更好的序列化 ”,無論他們的主要興趣是Java當前的序列化機制還是將來可能變成的東西。 從兩個角度來看,這都是一個有趣的文檔。
翻譯自: https://www.javacodegeeks.com/2019/06/motivations-behind-javas-maligned-serialization.html
總結
以上是生活随笔為你收集整理的Java恶意序列化背后的历史和动机的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分布式计算、云计算与大数据第十章
- 下一篇: java美元兑换,(Java实现) 美元