博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何防止JAVA反射对单例类的攻击?
阅读量:5094 次
发布时间:2019-06-13

本文共 6913 字,大约阅读时间需要 23 分钟。

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

  (1).饿汉式;

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

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

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

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

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

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

 

说明:

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

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

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

  SingletonReflectAttack.java    具体反射类

  SingletonReflectAttackMain.java    JUnit测试类

举例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, 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); //false19 }

 

测试结果: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     @Test11     public void testSingletonReflectAttack() throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException12     {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             else20             {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
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      * @throws IllegalArgumentException 5      * @throws SecurityException 6      * @throws InstantiationException 7      * @throws IllegalAccessException 8      * @throws InvocationTargetException 9      * @throws NoSuchMethodException10      */11     12     @Test13     public void testModifiedByattack() throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException14     {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
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      * @throws IllegalArgumentException 6      * @throws SecurityException 7      * @throws InstantiationException 8      * @throws IllegalAccessException 9      * @throws InvocationTargetException10      * @throws NoSuchMethodException11      */12     13     @Test14     public void testenumAttack() throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException15     {16         System.out.println("-------------枚举类型的单例模式被java反射攻击测试--------------");17         SingletonReflectAttack.enumAttack();18         System.out.println("----------------------------------------------------------");19     }

 

运行结果:

 

 4.总结与拓展

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

 

转载于:https://www.cnblogs.com/lthIU/p/6240128.html

你可能感兴趣的文章
找到IIS服务
查看>>
命令行解决mysql中文乱码
查看>>
C#代码执行中等待10秒
查看>>
window下nodejs环境和express插件的安装
查看>>
leetcode刷题正则表达式
查看>>
杨辉三角模板
查看>>
通过 PackageManager 获得你想要的 App 信息
查看>>
楼市捞金术:我是怎么在9个月把房价炒高两三倍的
查看>>
下载文件
查看>>
131125 - 关于对“一次元”、“二次元”、“三次元”的兴趣变化的奇思妙想
查看>>
HDU 2136 Largest prime factor
查看>>
POJ 3360 H-Cow Contest
查看>>
#Leetcode# 209. Minimum Size Subarray Sum
查看>>
2019省赛训练组队赛4.11周四 2014浙江省赛
查看>>
HDU 2084 数塔
查看>>
android 界面切换【转】
查看>>
JavaScript我学之七数组
查看>>
BETA冲刺(6/7)
查看>>
Poj(2679),SPFA,邻接表(主流写法)
查看>>
51nod 1277 字符串中的最大值(KMP算法)
查看>>