Java面向對象系列[v1.0.0][輸入流過濾器對反序列化對象有效性驗證]

輸入流過濾器對反序列化對象有效性驗證

Java9爲ObjectInputStream增加了setObjectInputFilter()、getObjectInputFilter()兩個方法,其中第一個方法用於爲對象輸入流設置過濾器,當程序通過ObjectInputStream反序列化對象時,過濾器的checkInput()方法將會被自動激發,用於檢查序列化數據是否有效
使用checkInput()方法檢查序列化數據時,有3種返回值:

  • Status.REJECTED:拒絕恢復
  • Status.ALLOWED:允許恢復
  • Status.UNDECIDED:未決定狀態,程序繼續執行檢查

ObjectInputStream將會根據ObjectInputFilter的檢查結果來決定是否執行反序列化,如果checkInput()方法返回Status.REJECTED,反序列化將會被阻止;如果checkInput()方法返回Status.ALLOWED,程序將可執行反序列化

import java.io.*;

public class FilterTest
{
	public static void main(String[] args)
	{
		try (
			// 創建一個ObjectInputStream輸入流
			var ois = new ObjectInputStream(new FileInputStream("object.txt")))
		{
			ois.setObjectInputFilter((info) -> {
				System.out.println("===執行數據過濾===");
				ObjectInputFilter serialFilter = ObjectInputFilter.Config.getSerialFilter();
					if (serialFilter != null) {
						// 首先使用ObjectInputFilter執行默認的檢查
						ObjectInputFilter.Status status = serialFilter.checkInput(info);
						// 如果默認檢查的結果不是Status.UNDECIDED
						if (status != ObjectInputFilter.Status.UNDECIDED) {
							// 直接返回檢查結果
							return status;
						}
					}
					// 如果要恢復的對象不是1個
					if (info.references() != 1)
					{
						// 不允許恢復對象
						return ObjectInputFilter.Status.REJECTED;
					}
					if (info.serialClass() != null &&
						// 如果恢復的不是Person類
						info.serialClass() != Person.class)
					{
						// 不允許恢復對象
						return ObjectInputFilter.Status.REJECTED;
					}
					return ObjectInputFilter.Status.UNDECIDED;
				});
			// 從輸入流中讀取一個Java對象,並將其強制類型轉換爲Person類
			var p = (Person) ois.readObject();
			System.out.println("名字爲:" + p.getName()
				+ "\n年齡爲:" + p.getAge());
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
	}
}

程序爲ObjectInputStream設置了ObjectInputFilter過濾器,程序重寫了checkInput()方法,顯示使用默認的ObjectInputFilter執行檢查,如果檢查結果不是Status.UNDECIDED, 程序直接返回檢查結果,然後程序通過FilterInfo檢查序列化數據,如果序列化數據中的對象不唯一(數據被污染),程序拒絕執行反序列化;如果序列化數據中的對象不是Person對象(數據被污染),程序拒絕執行反序列化。
通過這種檢查,程序可以保證反序列化出來的是唯一的Person對象,這樣就讓反序列化更加安全健壯

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