《Effective Java》-序列化

序列化

Item 85: Prefer alternatives to Java serialization

其他方法优先于Java序列化

使用Java中的readObject()方法进行反序列化是非常有风险的。

其一,为反序列化提供精心编写的代码流,则攻击者可以在底层硬件中执行本机的的任意代码。

其二,当攻击者向服务发送反序列化炸弹(deserialize bomb),就能够轻易完成一次拒绝服务(Denail of Service)攻击。

避免序列化攻击的最佳方式就是永远不要反序列化任何东西。 没有理由在你写的任何程序中使用Java序列化。

如果非要使用Java序列化,使用Java 9 支持的java.io.ObjectInputFilter

Item 86: Implement Serializable with great caution

谨慎地实现Serializable接口。

实现Serializable接口最大的代价就是,一旦某个类被发布,被存储在硬盘中,他可修改的灵活性就大大降低了。

如果使用了默认的序列化方式,一旦类的内部形式发生改变,那么发序列化老数据的时候,就会产生兼容性的问题。

实现序列化接口的第二个代价就是,会增加安全漏洞以及BUG的几率。通过序列化来创建对象,是一种超出语言之外的机制,很容易跳过系统的安全检查。

第三个代价是,增加了新类的测试负担。

如果一个专门为继承而生的类,和接口应当尽可能少地去实现序列化接口。内部类不应该去实现序列化接口

Item 87: Consider using a custom serialized form

考虑使用自定义的序列化形式。

在深思熟虑之前,不要贸然接受默认的序列化形式。

如果一个对象的物理表现形式和逻辑内容相同,可以考虑使用默认的序列化形式。不过,即使你确定了使用默认的序列化形式是合适的,依旧需要提供一个readObject方法来确保约束关系和安全性。

如果将某些字段设置为transient,那么反序列化的时候,字段值将会被初始化为默认值。如果是引用数据类型,则为null,基本数据类型则为0或者false。如果不能接受的话,必须提供readObject,在其实现内为你想要的属性去赋值。

此外,如果你在读取对象状态的其他方法上施加了同步,则也必须在序列化上强制这种同步。

一定要为实现序列化接口的类显式地声明一个序列化UID。不要去随意修改这个UID,除非你想要放弃系统的兼容性。

Item 88: Write readObject methods defensively

保护性地编写readObejct方法

当一个对象被反序列化的时候,若其某个字段包含客户端不存在的引用,则对此字段的保护性拷贝是至关重要的。

可以通过一个石蕊测试来确定,你是应该使用默认的readObject还是需要定义自己的readObject:你觉得为所有的非transient字段都添加到一个公有构造器,并且并施加任何参数校验是否合适?

禁止在readObject方法中引用任何用于被重写的方法。

Item 88: For instance control, prefer enum types to readResolve

为了控制实例,枚举类型优先于readResolve

对于任何的readObject方法,无论是显式的还是默认的,都会返回一个新的实例,该实例不同于创建时的实例。

readResolve的上述性质会破坏单例模式,为了保证单例的性质,可以使用枚举类对象。

事实上,如果你依赖于readResolve控制实例,所有的字段都应该被声明为transient的。

Item 90: Consider serialization proxies instead of seriallized instance

考虑使用序列化代理替代序列化实例

序列化模式相当简单:

  1. 为可序列化的类设计一个私有的静态嵌套类,精确表示外围类的逻辑状态
  2. 嵌套类的参数类型是外围类,并且拥有一个构造方法
  3. 构造器只从其参数中来复制值,而不做任何参数检查或者保护性拷贝

序列化代理有两个局限性:

  1. 不能与可以被客户端扩展的类相兼容
  2. 序列化代理模式增强的功能和安全性并不是没有代价的,保护性拷贝会降低系统的运行效率
相关推荐
码事漫谈6 小时前
多人共用一个 key,缓存命中率会不会因此降低?
后端
考虑考虑7 小时前
docker compose环境变量替换
运维·后端·自动化运维
武雄(小星Ai)8 小时前
飞书API上传26MB文件偶发失败:错误码9499与空响应体排坑实录
后端·api·排坑实录
徐小夕8 小时前
JitWord 4.0 万字分享:从协同工具到AI Word操作系统,聊聊3年产品创业史
前端·vue.js·后端
geovindu9 小时前
CSharp: Observer Pattern
开发语言·后端·观察者模式·设计模式·c#·.netcore·行为模式
Flynt10 小时前
把公司项目迁到 Spring Boot 4.0:编译通过只是开始
java·spring boot·后端
IT_陈寒10 小时前
Redis误用keys命令把生产环境搞崩了,血的教训
前端·人工智能·后端
她的男孩10 小时前
多租户和数据权限怎么共存?扒完拦截器注册链路,我找到 4 个隐蔽的坑
java·后端·架构
用户83562907805110 小时前
使用 Python 设置 Excel 页眉和页脚
后端·python
步行cgn10 小时前
IoC 控制反转:从概念到 Spring 的实现
后端