Java序列化需手动接管加密流程:将敏感字段声明为transient,重写private writeObject和readObject方法,按固定顺序加密写入IV与密文、解密还原,密钥须外部管理且禁用ECB,优先AES/GCM。

不能靠“自动”实现,必须手动接管序列化流程——Java 序列化本身不提供开箱即用的字段级加密能力。真正可行的方式是重写 private void writeObject(ObjectOutputStream) 和配套的 private void readObject(ObjectInputStream),在其中对敏感字段做加密写入与解密还原。
明确哪些字段需要加密并标记为 transient
先梳理业务中真正敏感的字段,比如 password、idCard、accessToken 等。这些字段应统一声明为 transient:
- 标记为
transient后,它们不会被defaultWriteObject()自动写入,避免明文出现在字节流里 - 强制你在
writeObject中显式处理——要么加密写入,要么彻底忽略,杜绝遗漏 - 反序列化时该字段初始值为
null或默认值,后续靠readObject中解密赋值
重写 writeObject:三步完成加密写入
方法签名必须严格为 private void writeObject(ObjectOutputStream out) throws IOException,JVM 才会调用它替代默认逻辑:
- 第一步:调用
out.defaultWriteObject(),让所有非transient字段正常序列化 - 第二步:对每个
transient敏感字段加密,推荐 AES/GCM 模式,每次生成新 IV(如 12 字节),确保密文不可预测 - 第三步:按固定顺序把 IV 和密文写入流,例如先
out.write(iv),再out.writeInt(ciphertext.length),最后out.write(ciphertext)
同步重写 readObject:严格按序解密还原
没有对称的 readObject,加密就失去意义,且极易抛出 StreamCorruptedException:
立即学习“Java免费学习笔记(深入)”;
- 先调用
in.defaultReadObject()恢复普通字段 - 再按
writeObject中的相同顺序读取:先读 IV(长度固定)、再读密文长度、最后读对应字节数的密文 - 用相同密钥和刚读到的 IV 解密,结果赋值给对应
transient字段,例如this.password = decrypt(iv, ciphertext)
密钥与算法的关键安全约束
加密本身不是目的,密钥管理和算法选择才是防线核心:
- 密钥绝不能硬编码在类里,应从环境变量、系统属性或配置中心加载
- 禁用 ECB 模式;优先选 AES/GCM(自带完整性校验),或 AES/CBC + 单独 HMAC
-
writeObject和readObject必须都是private,不可被继承或覆盖


















