serialization proxy pattern
Both the enclosing class and its serialization proxy must be declared to implement Serializable.
public class User implements Serializable {
...
private static class SerializationProxy implements Serializable {
...
}
}
the writeReplace method translates an instance of the enclosing class to its serialization proxy prior to serialization.
public class User implements Serializable {
...
private static class SerializationProxy implements Serializable {
...
}
// 2. writeReplace
private Object writeReplace() {
return new SerializationProxy(this);
}
}
to guarantee that such an attack would fail, merely add this readObject method to the enclosing class.
public class User implements Serializable {
...
private static class SerializationProxy implements Serializable {
...
}
private Object writeReplace() {
return new SerializationProxy(this);
}
// 3. readObject
private void ReadObject(ObjectInputStream stream) throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
}
the readResolve method creates an instance of the enclosing class using only its public API and therein lies the beauty of the pattern.
public class User implements Serializable {
...
private static class SerializationProxy implements Serializable {
...
// 4. readResolve
private Object readResolve() {
return new User(id, name);
}
}
private Object writeReplace() {
return new SerializationProxy(this);
}
private void ReadObject(ObjectInputStream stream) throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
}