java 如何防止单例模式被攻击?

是什么?怎么做?

参考:http://blog.csdn.net/u013256816/article/details/50525335

 

一、攻击单例模式的几种方式

(1)序列化

1.攻击方式

先写一个单例类,实现Serializable接口:

SerializableSingleton.java

写一个测试类:

TestAttack.java

运行结果为:

2.防范方法

在SerializableSingleton类中重定义readResolve方法:

SerializableSingleton.java

运行结果为:

其实最好的防范方法,就是单例类不要实现Serializable接口。

(2)clone方法

1.攻击方式

clone是Object类的一个方法,作用是拷贝对象(不常见)。它会把在堆上的对象所占用的内存空间拷贝一份然后返回,形成一个新的对象。

如果要使用clone方法,首先需要实现Cloneable接口。因为Object类中的clone方法被protected修饰,所以默认情况下只能在java.lang包中使用。如果要在包外使用,需要重写clone方法:

先写一个单例类,实现Cloneable接口,重写clone方法:

ComparableSingletion.java

写一个测试类:

TestAttack.java

运行结果为:

2.防范方法

使用clone可以获得一个新的单例类对象,显然违反了单例原则。

所以我们应该禁止单例类实现Cloneable接口/重写clone方法,防止被clone。

(3)反射

1.攻击方式

虽然new不能实例化带有私有构造方法的单例类,但是反射可以获取私有构造方法,从而实例化新的单例类对象。

先写一个单例类:

使用反射进行实例化:

TestAttack.java

这里的关键是setAccessible()方法。使用该方法后private构造方法变为可达,可以通过调用构造方法的方式创建对象,破坏单例。

运行结果为:

2.防范方法

解决思路为:“只允许调用一次构造方法(只允许创建一次对象),之后所有调用都会被拒绝,并且报出异常”。

运行结果为:

如果第二次调用构造方法创建对象,就会报出错误。

二、总结

防范反射比较普遍,其他情况需要特别留意。

发表评论

电子邮件地址不会被公开。 必填项已用*标注