好吧,這個在網上的講解一大堆了。我之所以寫這個呢,是爲了加深理解序列化和反序列化,當然還有反射。
序列化,它是讓Java對象脫離Java運行環境的一種手段,可以有效的實現多平臺之間的通信、對象持久化存儲。
序列化和反序列化的過程,
講解下,
- Java 序列化是指把 Java 對象轉換爲字節序列的過程,便於保存在內存、文件、數據庫中。----------ObjectOutputStream類的writeObject方法可以實現序列化。
- 反序列化是指把字節序列恢復爲 Java 對象的過程。----------ObjectInputStream 類的readObject方法用於反序列化。
那麼接下來,我們看下如何序列化吧,
條件:
- 類必須實現反序列化接口,同時設置serialVersionUID以便適用不同jvm環境。
- 可通過SerializationDumper這個工具來查看其存儲格式,主要包括Magic頭:0xaced,TC_OBJECT:0x73,TC_CLASS:0x72,serialVersionUID,newHandle
就這樣將String對象obj1序列化後寫入object文件,後反序列化得到對象obj2,執行後輸出:Hello world。
但是如果我們打開Object文件(默認在項目的文件夾下),
當然借用別人的,而我的是,
哈哈,可能借用的那張圖是用二進制打開方式打開的,而我使用的是筆記本,它的編碼不符合,所以出現了亂碼。不過這也證明了多出的是java序列化內容的特徵。
例如:Ac ed 00 05是java序列化內容的特徵,編碼後是rO0ABQ==。
好了,我們瞭解以及實踐了。那麼我們一般在什麼時候呢?
- http參數,cookie,sesion,存儲方式可能是base64(rO0),壓縮後的base64(H4sl),MII等。
- Servlets HTTP,Sockets,Session管理器包含的協議就包括JMX,RMI,JMS,JNDI等(\xac\xed)。
- xml Xstream,XMLDecoder等(HTTP Body:Content-Type:application/xml)。
- json(Jackson,fastjson) http請求中包含。
瞭解了這些基礎,那麼我們也就該瞭解反序列化的漏洞了。
如果你要驗證上面的代碼,那麼你就要自己找一個應用,好比我,
Test.class中MyObject類有一個共有屬性name,myObj實例化後將myObj.name賦值爲了“hi”,然後序列話寫入object,
漏洞發生在反序列化過程,MyObject類實現了Serializable接口,並重寫了readObject()函數(從源輸入流中讀取字節序列,反序列化成對象),這裏定製的行爲是打開計算器:
通過上面,我們瞭解到反序列化的漏洞是多麼可怕,你可以想象要是有黑客組織製作一系列的反序列化侵略命令,那麼你的電腦將遭所到什麼可怕的事情。
通過上面,我們瞭解到序列化和反序列化。對於這個功能我們絕對不可忽略,是因爲它有可能被某些人用來入侵,而且後果非常可怕。
好了,我們瞭解了這麼多。我們知道爲什麼要序列化嗎?
你知道對象在一般情況下,會隨着程序的終止而終止。但是在一些情況下,這些對象又不得不存在着。所以我們需要把這個對象的信息存儲起來,在下次運行的時候該對象被重建並保存程序上次運行的信息,這就是“持久化”。
對象的存儲可以是文件也可以是數據庫,而且還可以通過網絡來傳輸它。
嗯。。。
這也就意味着“持久化”可以把一個對象的生命週期不取決於程序是否運行了,而是生存於程序的調用之間。
但是上面能解決了我們的疑問了嗎?
其實,
還有這一部分。
參考資料:
Java編程思想 第18章 Java I/O系統 18.12 對象序列化