java-序列化
其他方法优先于java序列化
java反序列化是一个明显存在的风险,它不仅被应用直接广泛使用,也被java子系统RMI(远程方法调用)、JMX(Java管理扩展)和JMS等大量的间接被使用。
将不被信任的流进行反序列化,可能导致远程代码执行,拒绝服务,以及一系列其他的攻击。即使应用本身没有做错任何事情,也可能被攻击。
下面举一个例子, 在下面的例子中只要引入serializable, 就可以轻易地展开一次拒绝服务的攻击。
1 | static byte[] bomb() { |
每当反序列化一个不信任的字节流时,自己就需要试着去攻击它。避免序列化攻击的最佳方式是永远不要序列化任何东西
。主要原因
- 如果系统是机遇java序列化的 ,那么就无法迁移到别的平台或者别的语言的结构化数据表示法。
- java序列化存在很高的风险.
我们应该使用一种支持跨平台的数据结构例如: json 和protobuf。
谨慎地实现serializable 接口
实现了serializable 接口主要有以下代价:
如果想要这个类允许被序列化,那么非常简单 只需要在类上声明 implements serializable即可。但是这样做就会导致 一旦这个类被发布,
就大大降低了”改变这个类的实现”的灵活性,如果实现了serializable,那么他的所有的字节流编码就本城了它的导出API的一部分。如果接受了
默认的反序列化形式,那么这个类中的私有的实例都变成导出的API的一部分。这个不符合”最低限度地访问域”实现了serializable 接口之后增加了出现BUG 和安全漏洞爹可能性。
随着类发行新的版本,相关的测试负担也会增加。
以上几处 我们应该为了继承而设计类 我们应该尽可能少地去实现serializable 接口,用户的接口也应该少的继承serializable 接口。
考虑使用自定义的序列化形式
如果一个对象的物理表示法等同于它的逻辑内容,可能就适合于使用默认的序列化形式。例如:
1 | public class Name implements Serializable { |
即使你确定了默认的序列化形式是适合的,通常还必须提供一个readObject 方法以保证约束关系和安全性。
当一个对象的物理表示法与它的逻辑数据内容有实质性的区别时,使用默认序列形式会有以下4个缺点:
- 它使这个类的导出API 永远地束缚在该类的内部表示法上。
- 他会消耗过多的空间
- 他会消耗过多的时间
- 他会引起堆栈溢出