java中通过私有writeobject/readobject方法接管序列化流程,对transient敏感字段加密存储:先defaultwriteobject,再手动加密写入iv与密文,反序列化时严格镜像读取解密。

Java 中通过重写 writeObject 和 readObject 实现敏感字段加密存储,本质是接管默认序列化流程:让非敏感字段走标准路径,对密码、身份证号等手动加密后再写入字节流,并在反序列化时严格按序解密还原。
必须满足的签名与可见性要求
这两个方法不是普通工具方法,而是 JVM 识别的“钩子”:
- 必须声明为 private,不能是 public 或 protected
- 方法名、参数类型、异常声明必须完全匹配:
private void writeObject(ObjectOutputStream out) throws IOExceptionprivate void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException - 不能被继承或重载,加 static、改参数名、多抛异常都会导致 JVM 忽略,退回到默认行为
敏感字段要配合 transient 使用
这是避免明文泄露的关键设计习惯:
- 把 password、token、idCard 等声明为 transient,它们就不会被
defaultWriteObject()自动写入 - 这样能强制你在
writeObject中显式处理——不加密就等于没写,不会意外裸奔 - 若没加 transient 又没手动加密,该字段将以原始字符串形式直接出现在序列化流中
writeObject 里分三步完成加密写入
顺序不能错,否则反序列化会错位或失败:
- 第一步:调用
out.defaultWriteObject()—— 序列化所有非 transient、非 static 字段 - 第二步:对每个 transient 敏感字段加密,推荐 AES/GCM 模式(自带完整性校验),每次生成新 IV(如 12 字节)
- 第三步:按固定顺序把 IV 和密文写入流,例如:
out.write(iv);out.writeInt(ciphertext.length);out.write(ciphertext);
readObject 必须严格镜像 writeObject
解密逻辑和读取顺序必须一一对应:
- 第一步:先调用
in.defaultReadObject()恢复普通字段(必须最先执行) - 第二步:按写入顺序读取:先读 IV(如
new byte[12]),再读密文长度,最后读指定长度的密文字节 - 第三步:用相同密钥 + 读到的 IV 解密,结果赋值给对应 transient 字段,如
this.password = decrypt(iv, ciphertext); - 密钥绝不能硬编码,应从环境变量、系统属性或配置中心加载
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











