您的位置 首页 java

Java单例模式很容易破解,一旦破解就会造成系统性风险

Java的单例模式,其实破解起来很方便,一旦破解单例就会失效,变成复例模式,一般有两种方式破解。

第一:反射方式破解,这种方式通过反射获取类,然后调用该类的构造函数创建对象,所以我们只需要在构造函数上做限制就好。把绿色部分的注释去掉,就可以防止单例破解了。

   public class Singleton {
        private static Singleton instance;
        private Singleton() {
          //if(instance != null) {throw new RuntimeException("救命啊,有坏蛋想破我");}
        }
        public static synchronized Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }  

开始破解

  public static void main(String[] args) throws Exception {
        //反射获取单例类
        Class<Singleton> claz = (Class<Singleton>) Class.forName("Singleton");
        //通过反射获得原本私有的无参构造器
        Constructor<Singleton> c = claz.getDeclaredConstructor(null);
        //关闭安全检查
        c.setAccessible(true);
        //通过构造器实例化对象
        Singleton s3 = c.newInstance();
        Singleton s4 = c.newInstance();
        System.out.println(s3);
        System.out.println(s4);
    }  

运行结果:

 singleton.Singleton@6d06d69c
singleton.Singleton@7852e922  

方式二:序列化方式,这种方式问题主要是发生在反序列化的环节,每次反序列化都会生成新的对象,如果我们再生成新的对象时候让他返回老的对象就可以防止了,readResolve方法做控制就好

 public class Singleton implements Serializable {
        private static Singleton instance;
        private Singleton() {
        }
        public static synchronized Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
  
  //private Object readResolve(){
//return instance;
//}
    }  

开始破解:

 public static void main(String[] args) throws Exception {
        Singleton s1 = Singleton.getInstance();
        System.out.println(s1);
  
        //先序列化
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(os);
        oos.writeObject(s1);
//反序列化
        InputStream is = new ByteArrayInputStream(os.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(is);
        Singleton s2 = (Singleton) ois.readObject();

        System.out.println(s2);        
    }  

文章来源:智云一二三科技

文章标题:Java单例模式很容易破解,一旦破解就会造成系统性风险

文章地址:https://www.zhihuclub.com/169717.shtml

关于作者: 智云科技

热门文章

网站地图