安全获取并恢复Java对象的核心是禁用JDK原生序列化,改用Jackson JSON序列化;必须停用JdkSerializationRedisSerializer,配置GenericJackson2JsonRedisSerializer并禁用enableDefaultTyping,对敏感字段脱敏,日期统一用ISO-8601格式。

从 Redis 安全获取并恢复 Java 对象,核心不是“怎么反序列化”,而是“不让危险反序列化发生”。Redis 本身不执行代码,但若你用原生 Java 序列化存对象(JdkSerializationRedisSerializer),再从不可信来源读取、反序列化,就等于主动打开远程代码执行(RCE)大门。真正安全的做法是绕过 Java 原生序列化,改用无执行能力的格式,并在必要环节加白名单与校验。
优先禁用原生 Java 序列化
Spring Data Redis 默认使用 JdkSerializationRedisSerializer,它直接调用 ObjectInputStream.readObject(),只要字节流被篡改或 Redis 被未授权写入,就可能触发 Commons Collections 等 gadget 链。这不是配置问题,是设计缺陷。
- 立即停用默认序列化器,不要依赖“只存内部数据”这种假设——缓存污染、配置错误、运维误操作都可能导致 Redis 写入恶意 payload
- 检查项目中所有
RedisTemplate和StringRedisTemplate的 bean 定义,确认未隐式启用 JDK 序列化 - 若历史数据已用 JDK 方式存储,需制定迁移计划,不能边跑边修
改用 JSON 序列化(推荐方案)
用 Jackson 将对象转为字符串存入 Redis,反序列化时只解析为 DTO 或 Map,不触发类加载、不执行任何方法,天然免疫反序列化 RCE。
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型
- 配置
RedisTemplate使用GenericJackson2JsonRedisSerializer,并关闭不安全特性:mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL)必须禁用,否则会引入类型信息导致 Jackson 自动实例化任意类 - 对敏感字段(如 token、密钥)做手动脱敏或加密,JSON 本身不提供字段级保护
- 注意时区、日期格式等兼容性,建议统一用 ISO-8601 字符串表示
LocalDateTime
若必须保留二进制存储,至少做三层过滤
仅当遗留系统强依赖字节流接口、且无法改造协议时,才考虑加固原生序列化路径。这属于高风险兜底方案,不应作为首选。
- 自定义
RedisTemplate的 value 序列化器,继承RedisSerializer,在deserialize()方法内先校验字节流前缀、长度、魔数(如固定校验头),拦截明显异常包 - 包装
ObjectInputStream,显式设置ObjectInputFilter白名单:ois.setObjectInputFilter(ObjectInputFilter.Config.createFilter("com.myapp.dto.*;java.lang.String;java.time.*")) - JVM 启动参数强制全局过滤:
-Djdk.serialFilter="maxdepth=3;maxrefs=500;maxarray=10000;pattern=com.myapp.dto.**;!"
运行时防护与监控补位
再严的过滤也防不住 0day gadget,需叠加运行时感知能力。
- 在反序列化入口处记录类名、调用栈、请求来源 IP(如有),异常时告警而非静默失败
- 用 JVM Agent(如 OpenTelemetry 或自研字节码插桩)监控
Runtime.exec、ProcessBuilder.start等敏感方法调用,发现即熔断 - 定期扫描依赖,重点排查
commons-collections、groovy、ysoserial相关 jar 包
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










