这个Singleton对序列化和reflection攻击都有抵抗力吗?

以下代码是否对序列化和reflection攻击都有抵抗力?

public class Example{ private static Example instance=new Example(); private Example(){} public static Example getInstance(){ return instance; } } 

引用约书亚布洛赫,

从版本1.5开始,有第三种方法来实现单例。 只需使用一个元素创建一个枚举类型:

  // Enum singleton - the preferred approach public enum Elvis{ INSTANCE; public void leaveTheBuilding(){...} } 

这种方法在function上等同于公共字段方法,除了它更简洁,免费提供序列化机制,并提供防止多个实例化的铁定保证,即使面对复杂的序列化或reflection攻击

参考 。

编辑:

约书亚布洛赫说,如果你想知道原因

要保持单例保证,必须声明所有实例字段为transient并提供readResolve方法。 否则,每次反序列化序列化实例时,都会创建一个新实例……

不它不是。 有一种更好的技术。

尝试这样的事情:

 public enum Elvis { INSTANCE; public static boolean isThereOnlyOneElvis() { return true; } } // In your code: if ( !Elvis.INSTANCE.isThereOnlyOneElvis() ) { System.err.println("Liar !!!"); } 

OO设计并不意味着防止攻击,恕我直言。 但是,由于理解不当,不尊重合同,无能或编程错误,防止不恰当地使用您的类和错误会很有用。

由于您的Example类不可序列化,我会说在这种情况下序列化不是问题。 关于反思,如果有人用它来创建你的单身的另一个实例,那么他显然是恶意的IMO,并且无论如何都有可能在脚下射击自己。

就reflection而言,上下文中的单例不是reflectioncertificate。 你可以使用setAccssible(true)来获取私有构造函数并实例化单例。 您可以在http://technonstop.com/java-singleton-reflection-and-lazy-initialization获取有关此事的更多详细信息。

 package com.eiq.singleton; import java.io.Serializable; public class SingleTonDemo implements Cloneable, Serializable { // order of declaring variables objCount and SingleTonDemo should be same. private static int objCount = 0; private static SingleTonDemo obj = new SingleTonDemo(); //this value is not needed, to test whether the object value only, you can remove it, the code will work int i = 10; private SingleTonDemo() { // logic to throw exception if we are trying to create object through reflection. if (objCount == 0) { synchronized (SingleTonDemo.class) { if (objCount == 0) objCount++; } } else { throw new RuntimeException( "Singleton class, Object creation is restricted"); } } public static SingleTonDemo getInstance() { return obj; } // To avoid duplication @Override public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException( "Cannot Duplicate Single Ton Object"); } // To avoid serialization and deserialization problems public Object readResolve() { return SingleTonDemo.getInstance(); } } In the above program will create only one object in all the cases like serialization, cloning, reflection and factory method etc. This is the testing code: package com.eiq.singleton; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Constructor; public class TestSingleTon { private static final String FILE_PATH = "E:/suman/singleton.txt"; public static void main(String[] args) throws Exception { System.out .println("Creating through factory method of SingleTonDemo.getInstance()"); SingleTonDemo obj = SingleTonDemo.getInstance(); System.out.println(obj + " obj i=" + obj.i); // Serializing the object FileOutputStream fos = new FileOutputStream(FILE_PATH); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(obj); System.out.println(); System.out.println("Object creation through deserialization mechanism"); // Returns the already created object if we trying to create object // through Deserialization mechanism. // Deserializing the object first time FileInputStream fis1 = new FileInputStream(FILE_PATH); ObjectInputStream ois1 = new ObjectInputStream(fis1); SingleTonDemo deserializedObj1 = (SingleTonDemo) ois1.readObject(); System.out.println(deserializedObj1 + " deserializedObj1 i=" + deserializedObj1.i); // Deserializing the object second time, in both the case returns same // object FileInputStream fis2 = new FileInputStream(FILE_PATH); ObjectInputStream ois2 = new ObjectInputStream(fis2); SingleTonDemo deserializedObj2 = (SingleTonDemo) ois2.readObject(); System.out.println(deserializedObj2 + " deserializedObj2 i=" + deserializedObj2.i); // throws exception if we duplicate the object // SingleTonDemo ob = (SingleTonDemo) obj.clone(); // Through Reflection System.out.println(); System.out .println("=====Throwing Exception if we are trying to create object through Reflection======="); Class rObj = (Class) Class .forName("com.eiq.singleton.SingleTonDemo"); Constructor[] constructors = (Constructor[]) rObj .getDeclaredConstructors(); for (Constructor constructor : constructors) { constructor.setAccessible(true); SingleTonDemo reflObj1 = constructor.newInstance(); System.out.println(reflObj1 + " reflObj1 i=" + reflObj1.i); } } }