在Effective Java(第7章)中,它说
另请注意,我们没有使用Date的克隆方法来制作防御性副本。因为Date是非最终的,所以不能保证clone方法返回一个类为java.util.Date的对象:它可能返回一个专门为恶意恶作剧设计的不可信子类的实例。例如,这样的子类可以在创建时记录对私有静态列表中每个实例的引用,并允许攻击者访问该列表。这将使攻击者在所有实例中自由统治。要防止此类攻击,请不要使用克隆方法制作类型可由不信任方进行子类化的参数的防御副本。
我不太明白它的解释。为什么clone()不返回Date对象?该实例如何成为不受信任的子类?
答案 0 :(得分:3)
考虑以下代码:
public class MaliciousDate extends Date { /** malicious code here **/ }
public class SomeClass {
public static void main(String[] args) {
MaliciousDate someDate = new MaliciousDate();
Date copyOfMaliciousDate = someDate;
Date anotherDate = copyOfMaliciousDate.clone();
}
}
由于copyOfMaliciousDate
类型为Date
,您可以致电clone()
,它会返回Date
个对象,但会在clone
上调用copyOfMaliciousDate
执行MaliciousDate
类中编写的代码,因为copyOfMaliciousDate
中存储的实例是MaliciousDate
。
答案 1 :(得分:2)
clone()
被广泛认为是一次失败的实验。在这种情况下,传入Date
的人可能已经传递了EvilDate extends Date
clone()
方法偷偷地返回了一个仍然可由他人修改的副本。
答案 2 :(得分:0)
我还没有阅读过您引用的书,但是该段的理由不充分,也无法抵御任何形式的攻击。</ p>
引文中提到,具有将代码加载到程序中的能力的攻击者可能会使用恶意方法提交Date
子类,例如,从Date
返回clone
的子类。
但这只是具有加载代码能力的攻击者可能造成伤害的次要方式。他们还可以:
System.exit()
停止程序,然后如果攻击者在您的进程中运行代码,则游戏结束并且您的进程受到威胁,而这个愚蠢的后卫将无济于事。
从设计的角度来看,也许您认为克隆是不好的,这很好,但是请不要假装不使用它会保护您免受某种安全威胁,因为它不会。