首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 序列化進階:你可能不知道的 5 件事(三)——簽名封裝、代理模式與驗證機制

     編輯:Java 相關知識

3. 序列化資料可簽名與密封

若需對整個物件進行加密與簽名,最簡單方式是使用 javax.crypto.SealedObject 與 java.security.SignedObject 包裝器。兩者皆實作 Serializable,可將原物件包裝成「密封盒」:

  • SealedObject:需對稱金鑰解密,金鑰須獨立管理。
  • SignedObject:用於資料驗證,同樣需獨立管理金鑰。

組合使用可輕鬆實現序列化資料的機密性與完整性,無需手動處理加密/簽名細節。

4. 序列化允許放入代理物件

當類別包含核心資料欄位,可由此推導其他欄位時,無需序列化完整物件。可將欄位標記 transient,但每次存取仍需檢查初始化。更好的方式是指定 Flyweight 或 代理 物件寫入序列化流:

  • 實作 writeReplace():序列化時回傳代理物件替換原物件。
  • 實作 readResolve():反序列化時由代理物件還原真實物件。

打包與解包代理範例

class PersonProxy implements java.io.Serializable {
    public PersonProxy(Person orig) {
        data = orig.getFirstName() + "," + orig.getLastName() + "," + orig.getAge();
        if (orig.getSpouse() != null) {
            Person spouse = orig.getSpouse();
            data += "," + spouse.getFirstName() + "," + spouse.getLastName() + "," + spouse.getAge();
        }
    }
    public String data;

    private Object readResolve() throws java.io.ObjectStreamException {
        String[] pieces = data.split(",");
        Person result = new Person(pieces[0], pieces[1], Integer.parseInt(pieces[2]));
        if (pieces.length > 3) {
            result.setSpouse(new Person(pieces[3], pieces[4], Integer.parseInt(pieces[5])));
            result.getSpouse().setSpouse(result);
        }
        return result;
    }
}

public class Person implements java.io.Serializable {
    // ... 建構子、getter/setter ...
    private Object writeReplace() throws java.io.ObjectStreamException {
        return new PersonProxy(this); // 序列化時替換為代理
    }
    private String firstName, lastName;
    private int age;
    private Person spouse;
}

此模式大幅減少序列化體積,並可隱藏敏感欄位或簡化物件圖結構。

5. 信任,但要驗證

反序列化後不應盲目信任資料完整性。實作 ObjectInputValidation 介面並覆寫 validateObject(),發現欄位值異常時拋出 InvalidObjectException,確保資料一致性(「以防萬一」的防禦性程式設計)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved