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

在我的上篇随笔中,我们知道了创建单例类有以下几种方式:

(1).饿汉式;

(2).懒汉式(、加同步锁的懒汉式、加双重校验锁的懒汉式、防止指令重排优化的懒汉式);

(3).登记式单例模式;

(4).静态内部类单例模式;

(5).枚举类型的单例模式。

在上面的5种实现方式中,除了枚举类型外,其他的实现方式是可以被JAVA的反射机制给攻击的,即使他的构造方法是私有化的,我们也可以做一下处理,从外部得到它的实例。

下面,我将会举例来说明:

8b4504a5bad69d8fe0e0ea007e70cdd0.png

说明:

Singleton.java     没有经过处理的饿汉式单例模式实现方式

Singleton6.java   枚举类型的单例模式

SingletonNotAttackByReflect.java         经过处理的饿汉式单例模式实现方式

SingletonReflectAttack.java    具体反射类

SingletonReflectAttackMain.java    JUnit测试类

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

Singleton.java    代码清单【1.1】

1 public classSingleton2 {3 private static boolean flag = true;4 private static final Singleton INSTANCE = newSingleton();5

6 privateSingleton()7 {8 }9

10 public staticSingleton newInstance()11 {12 returnINSTANCE;13 }14

15 }

SingletonReflectAttack.java  代码清单【1.2】

1 /**

2 * 单例模式被java反射攻击3 *@throwsIllegalArgumentException4 *@throwsInstantiationException5 *@throwsIllegalAccessException6 *@throwsInvocationTargetException7 *@throwsSecurityException8 *@throwsNoSuchMethodException9 */

10

11 public static void attack() throwsIllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException12 {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 *@throwsNoSuchMethodException4 *@throwsInvocationTargetException5 *@throwsIllegalAccessException6 *@throwsInstantiationException7 *@throwsSecurityException8 *@throwsIllegalArgumentException9 */

10 @Test11 public void testSingletonReflectAttack() throwsIllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException12 {13 System.out.println("-------------单例模式被java反射攻击测试--------------");14 SingletonReflectAttack.attack();15 System.out.println("--------------------------------------------------");16 }17

运行结果:

f354d06db9149c90e736f16bc6c665c6.png

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

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

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

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

SingletonNotAttackByReflect.java   代码清单【2.1】

1 packagecom.lxf.singleton;2

3 importjavax.management.RuntimeErrorException;4

5 public classSingletonNotAttackByReflect6 {7 private static boolean flag = false;8 private static final SingletonNotAttackByReflect INSTANCE = newSingletonNotAttackByReflect();9

10 //保证其不被java反射攻击

11 privateSingletonNotAttackByReflect()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 staticSingletonNotAttackByReflect getInstance()28 {29 returnINSTANCE;30 }31

32

33 }

SingletonReflectAttack.java  代码清单【2.2】

1 public static voidmodifiedByAttack()2 {3 try

4 {5 Class classType = SingletonNotAttackByReflect.class;6 Constructor 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 *@throwsIllegalArgumentException5 *@throwsSecurityException6 *@throwsInstantiationException7 *@throwsIllegalAccessException8 *@throwsInvocationTargetException9 *@throwsNoSuchMethodException10 */

11

12 @Test13 public void testModifiedByattack() throwsIllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException14 {15 System.out.println("-------------修改后的单例模式被java反射攻击测试--------------");16 SingletonReflectAttack.modifiedByAttack();17 System.out.println("----------------------------------------------------------");18 }

运行结果:

7af48995381659236aa6d09a34160801.png

4ec195779958afa82f2cc0dcb2ab2941.png

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

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

Singleton6.java    代码清单【3.1】

1 public enumSingleton62 {3 INSTANCE;4

5 privateResource instance;6

7 Singleton6()8 {9 instance = newResource();10 }11

12 publicResource getInstance()13 {14 returninstance;15 }16

17

18 }

SingletonReflectAttack.java  代码清单【3.2】

1 public static void enumAttack() throwsSecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException2 {3 try

4 {5 Class classType = Singleton6.class;6 Constructor constructor =(Constructor) 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 *@throwsIllegalArgumentException6 *@throwsSecurityException7 *@throwsInstantiationException8 *@throwsIllegalAccessException9 *@throwsInvocationTargetException10 *@throwsNoSuchMethodException11 */

12

13 @Test14 public void testenumAttack() throwsIllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException15 {16 System.out.println("-------------枚举类型的单例模式被java反射攻击测试--------------");17 SingletonReflectAttack.enumAttack();18 System.out.println("----------------------------------------------------------");19 }

运行结果:

2481115065aa832917ccb534ae5fc3c7.png

4.总结与拓展

所以,在项目开发中,我们要根据实际情况,选择最安全的单例模式实现方式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值