如何防止JAVA反射对单例类的攻击?

加静态标志位,构造方法通过synchronized修饰。或者枚举

举例1:不经过处理的单例类被JAVA反射机制攻击

Singleton.java    代码清单【1.1】

 1 public class Singleton
 2 {
 3     private static boolean flag = true;
 4     private static final Singleton INSTANCE = new Singleton();
 5
 6     private Singleton()
 7     {
 8     }
 9
10     public static Singleton newInstance()
11     {
12         return INSTANCE;
13     }
14
15 }

SingletonReflectAttack.java  代码清单【1.2】

 1 /**
 2      * 单例模式被java反射攻击
 3      * @throws IllegalArgumentException
 4      * @throws InstantiationException
 5      * @throws IllegalAccessException
 6      * @throws InvocationTargetException
 7      * @throws SecurityException
 8      * @throws NoSuchMethodException
 9      */
10
11     public static void attack() throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException
12     {
13         Class<?> classType = Singleton.class;
14         Constructor<?> constructor = classType.getDeclaredConstructor(null);
15         constructor.setAccessible(true);
16         Singleton singleton = (Singleton) constructor.newInstance();
17         Singleton singleton2 = Singleton.newInstance();
18         System.out.println(singleton == singleton2);  //false
19     }

测试结果:SingletonReflectAttackMain.java  代码清单【1.3】

 1 /**
 2      * 1.测试单例模式被java反射攻击
 3      * @throws NoSuchMethodException
 4      * @throws InvocationTargetException
 5      * @throws IllegalAccessException
 6      * @throws InstantiationException
 7      * @throws SecurityException
 8      * @throws IllegalArgumentException
 9      */
10     @Test
11     public void testSingletonReflectAttack() throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException
12     {
13         System.out.println("-------------单例模式被java反射攻击测试--------------");
14         SingletonReflectAttack.attack();
15         System.out.println("--------------------------------------------------");
16     }
17     

运行结果:

  返回结果为false,说明创建了两个不同的实例。通过反射获取构造函数,然后调用setAccessible(true)就可以调用私有的构造函数;所以创建出来的两个实例时不同的对象。

如果要抵御这种攻击,就要修改构造器,让他在被要求创建第二个实例的时候抛出异常。

下面,我们对饿汉式单例模式做修改。

举例2.经过处理的单例类,JAVA反射机制攻击测试

SingletonNotAttackByReflect.java   代码清单【2.1】

 1 package com.lxf.singleton;
 2
 3 import javax.management.RuntimeErrorException;
 4
 5 public class SingletonNotAttackByReflect
 6 {
 7     private static boolean flag = false;
 8     private static final SingletonNotAttackByReflect INSTANCE = new SingletonNotAttackByReflect();
 9
10     //保证其不被java反射攻击
11     private SingletonNotAttackByReflect()
12     {
13         synchronized (SingletonNotAttackByReflect.class)
14         {
15             if(false == flag)
16             {
17                 flag = !flag;
18             }
19             else
20             {
21                 throw new RuntimeException("单例模式正在被攻击");
22             }
23
24         }
25     }
26
27     public static SingletonNotAttackByReflect getInstance()
28     {
29         return INSTANCE;
30     }
31
32
33 }

SingletonReflectAttack.java  代码清单【2.2】

 1 public static void modifiedByAttack()
 2     {
 3         try
 4         {
 5             Class<SingletonNotAttackByReflect> classType = SingletonNotAttackByReflect.class;
 6             Constructor<SingletonNotAttackByReflect> constructor = classType.getDeclaredConstructor(null);
 7             constructor.setAccessible(true);
 8             SingletonNotAttackByReflect singleton = (SingletonNotAttackByReflect) constructor.newInstance();
 9             SingletonNotAttackByReflect singleton2 = SingletonNotAttackByReflect.getInstance();
10
11             System.out.println(singleton == singleton2);
12         }
13         catch (Exception e)
14         {
15             e.printStackTrace();
16         }
17
18     }

SingletonReflectAttackMain.java  代码清单【2.3】

 1 /**
 2      * 2.修改后的单例模式被java反射攻击测试.
 3      * 攻击失败
 4      * @throws IllegalArgumentException
 5      * @throws SecurityException
 6      * @throws InstantiationException
 7      * @throws IllegalAccessException
 8      * @throws InvocationTargetException
 9      * @throws NoSuchMethodException
10      */
11
12     @Test
13     public void testModifiedByattack() throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException
14     {
15         System.out.println("-------------修改后的单例模式被java反射攻击测试--------------");
16         SingletonReflectAttack.modifiedByAttack();
17         System.out.println("----------------------------------------------------------");
18     }

运行结果:

在之前,我们也介绍过,枚举类型的单例模式也可以防止被JAVA反射攻击,这里我们简单测试一下。

举例3:枚举类型的单例模式被JAVA反射机制攻击测试

Singleton6.java    代码清单【3.1】

 1 public enum Singleton6
 2 {
 3     INSTANCE;
 4
 5     private Resource instance;
 6
 7     Singleton6()
 8     {
 9         instance = new Resource();
10     }
11
12     public Resource getInstance()
13     {
14         return instance;
15     }
16
17
18 }

SingletonReflectAttack.java  代码清单【3.2】

 1     public static void enumAttack() throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException
 2     {
 3         try
 4         {
 5             Class<Singleton6> classType = Singleton6.class;
 6             Constructor<Singleton6> constructor =(Constructor<Singleton6>) classType.getDeclaredConstructor();
 7             constructor.setAccessible(true);
 8             constructor.newInstance();
 9
10         }
11         catch (Exception e)
12         {
13             e.printStackTrace();
14         }

SingletonReflectAttackMain.java  代码清单【3.3】

 1 /**
 2      * 枚举类型的单例模式被java反射攻击测试
 3      * 攻击失败
 4      *
 5      * @throws IllegalArgumentException
 6      * @throws SecurityException
 7      * @throws InstantiationException
 8      * @throws IllegalAccessException
 9      * @throws InvocationTargetException
10      * @throws NoSuchMethodException
11      */
12
13     @Test
14     public void testenumAttack() throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException
15     {
16         System.out.println("-------------枚举类型的单例模式被java反射攻击测试--------------");
17         SingletonReflectAttack.enumAttack();
18         System.out.println("----------------------------------------------------------");
19     }

运行结果:

原文:https://www.cnblogs.com/lthIU/p/6240128.html

原文地址:https://www.cnblogs.com/luquanjian/p/10886793.html

时间: 2024-10-12 02:07:30

如何防止JAVA反射对单例类的攻击?的相关文章

关于java写一个单例类(面试手写题)

package com.shundong.javacore; /** * java写一个简单的单例类 * @author shundong * */ class Singleton { //使用一个类变量来缓存曾经创建的实例 private static Singleton instance; //对构造进行隐藏(private) private Singleton(){} /** * 提供一个静态方法 * 该方法加入了自定义控制 保证只产生一个Singleton对象 * @return 返回S

Java中Class和单例类的作用与类成员的理解

Java中Class类的作用与深入理解 在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识.这个信息跟踪着每个对象所属的类.JVM利用运行时信息选择相应的方法执行.而保存这些信息的类称为Class.可能容易产生混淆,容易想到class.不过二者没什么关系,class不过是描述类的一个关键字.而Class却是保存着运行时信息的类. 它能做什么?Class类可以帮助我们在程序运行时分析类,说白了就是获取类中的值.可能瞬间就想到了反射,没错!Class一般就是和反射配套使

java单例类/

java单例类  一个类只能创建一个实例,那么这个类就是一个单例类 可以重写toString方法 输出想要输出的内容 可以重写equcal来比较想要比较的内容是否相等 对于final修饰的成员变量 一但有了初始值,就不能被重新赋值 static修饰的成员变量可以在静态代码块中 或申明该成员时指定初始值 实例成员可以在非静态代码块中,申明属性,或构造器中指定初始值 final修饰的变量必须要显示初始化 final修饰引用变量不能被重新赋值但是可以改变引用对象的内容分(只要地址值不变) final修

java 核心学习笔记(四) 单例类

如果一个类始终只能创建一个实例,那么这个类被称作单例类. 一些特殊的应用场景可能会用到,为了保证只能创建一个实例,需要将构造方法用private修饰,不允许在类之外的其它地方创建类的实例. 又要保证可以创建该类的实例,所以需要一个public方法来创建该类的实例,由于在创建之前并没有该类的对象存在,所以只能使用类来调用此方法,故用static修饰. 同时需要将该类创建得到的实例分配一个引用才能知道该实例是否存在与是否唯一,所以需要一个成员变量保存创建的对象,同时由于该对象由上述静态方法创建,则该

java 单例类

·单例类 单实例类,就是这个类只能创建一个对象,保证了对象实例的唯一性. 例子:单实例类 class Singleton { private static Singleton instance; //使用static修饰,因为它要在该类的静态方法中被访问,作用 //是一个引用变量指向对象. private Singleton(){}; //提供一个私有的构造器,使用方法来控制它创建对象的个数. //方法必须是public的和static的,因为方法要公开被下面的类调用并且下面的s1引用变量获取方

java单例类的几种实现

一,最简单的方式 public class Singleton{ private Singleton(){}; private static Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; } } 首先构造函数声明为private,防止被外部创建该类的实例.声明一个static的成员变量instance并分配实例,当Singleton类被加载时,instan

单例类多线程

作为设计模式理论中的Helloworld,相信学习java语言的人,都应该听说过单例模式.单例模式作为对象的一种创建模式,它的作用是确保某一个类在整个系统中只有一个实例,而且自行实例化并向整个系统提供这个实例. 由此可见,单例模式具有以下的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一的实例. 单例类必须给所有其他对象提供这一实例. 由于Java语言的特点,使得单例模式在Java语言的实现上有自己的特点.这些特点主要表现在单例类如何将自己实例化. 饿汉式单例类 饿汉式单例类是在Ja

Java软件设计模式------单例设计模式

Java软件设计模式一共分为23种; 一般常用的有: 单例设计模式 装饰设计模式 工厂设计模式 单例设计模式(以后的用处:spring框架IOC,默认创建的对象都是单例的): 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案. 单例设计模式分为两种(饿汉式和懒汉式): ①饿汉式(常用): 特

设计模式中饿汉式单例类和懒汉式单例类

单例模式的特点为: *单例类只有一个实例. *单例类必须自己创建自己的唯一实例. *单例类必须给所有其他对象提供这一实例. 饿汉式单例类: 而饿汉式单例类则在java语言中是最为简单的单例类,这是一个描述饿汉式单例类的类图的实现. 此类图中,此类已经将自己实例化. 源码为: package singleton; public class EagerSingleton { private static EagerSingleton instance=new EagerSingleton(); /*