Java对象序列化敏感字段需重写writeObject和readObject方法:先用transient隔离字段,再手动AES/GCM加密写入IV与密文,解密时按序读取并赋值,密钥须外部加载、IV每次生成且长度固定。

Java 对象序列化时对敏感字段加密,不是加个注解或配个开关就能生效的事——必须主动接管序列化流程,通过重写 private writeObject 和 private readObject 方法,手动完成加密写入与解密还原。核心在于:用 transient 隔离敏感字段,再在自定义方法中显式加密,确保明文不进字节流。
用 transient 标记敏感字段
这是第一步,也是隔离明文的关键动作:
- 把 password、idCard、token 等字段声明为 transient,它们就不会被
defaultWriteObject()自动写入 - 如果不加 transient,又没手动加密,该字段就会以明文形式出现在序列化字节流中,等于裸奔
- 加了 transient 后,该字段反序列化后默认为 null 或 0,必须由你手动解密赋值,避免遗漏
重写 writeObject:三步写入加密数据
方法签名必须严格是 private void writeObject(ObjectOutputStream out) throws IOException,JVM 才会调用它:
- 先调用
out.defaultWriteObject()—— 序列化所有非 transient、非 static 字段 - 对 transient 敏感字段加密,推荐 AES/GCM 模式(带完整性校验),每次生成新 IV(如 12 字节)
- 按固定顺序写入:先写 IV(
out.write(iv)),再写密文长度(out.writeInt(len)),最后写密文字节(out.write(cipher))
配套重写 readObject:按序解密并赋值
没有对称的 readObject,加密就失去意义,还容易抛 StreamCorruptedException:
立即学习“Java免费学习笔记(深入)”;
- 先调用
in.defaultReadObject()恢复普通字段 - 严格按 writeObject 的顺序读取:读 IV(如
byte[12])、读密文长度、读对应长度的密文字节 - 用相同密钥和 IV 解密,结果赋给 transient 字段,例如
this.password = decrypt(iv, cipher);
密钥与 IV 的安全处理
这两项处理不当,整个加密形同虚设:
- 密钥绝不能硬编码在类里,建议从环境变量、系统属性或安全配置中心加载
- IV 必须随密文一起序列化,但不能固定;每次加密都生成新 IV,并确保长度一致(GCM 推荐 12 字节)
- 禁用 ECB 模式;AES/CBC 必须配合 HMAC 校验,AES/GCM 是更优选择


















