SerializablePermission不用于增强变量反序列化安全,而是限制序列化行为的权限类;真正防护变量反序列化的机制是Java 9+的反序列化过滤器(ObjectInputFilter),支持类/字段级白名单、深度与长度限制等精细控制。

SerializablePermission 本身不用于“增强变量反序列化安全”,它是一个 Java 安全管理器(SecurityManager)体系下的权限控制类,作用是限制哪些代码有资格执行序列化操作(比如调用 ObjectOutputStream.writeObject()),而不是在反序列化阶段校验或过滤具体字段或变量。
真正用于控制反序列化安全、防止恶意数据攻击(如 gadget 链利用、敏感字段篡改、任意代码执行)的机制,是 反序列化过滤器(Deserialization Filters),自 Java 9 引入、Java 17 成为强制推荐机制。它和 SerializablePermission 属于不同层级:前者是 JVM 级运行时策略控制,后者是细粒度字节流解析前的安全门禁。
反序列化过滤器才是变量级安全的核心手段
Java 9+ 提供了 ObjectInputFilter 接口及配套配置方式,可精确控制哪些类/包/字段允许被反序列化。关键点:
- 通过
System.setProperty("jdk.serialFilter", "pattern")全局设置白名单或黑名单模式 - 或在创建
ObjectInputStream时显式传入ObjectInputFilter实例,实现 per-stream 精细控制 - 支持通配符(如
java.util.*)、深度限制(maxdepth=5)、数组长度限制(maxarray=10000)等 - 能有效拦截非预期类型(如
javax.management.BadAttributeValueExpException)、阻止 gadget 链中关键类加载
SerializablePermission 的真实用途与局限
它仅在启用 SecurityManager 且策略明确授予 "enableSerialization" 权限时,才允许当前代码调用序列化方法。但它完全不干预反序列化过程本身,也不检查字段名、值、类型合法性:
- 即使你用
new SerializablePermission("enableSerialization")授予权限,也无法阻止反序列化一个含恶意readObject()方法的类 - 它不识别
transient字段、不校验serialVersionUID、不过滤某个具体变量(如 password、token)是否被还原 - 现代 JDK(尤其是 17+)已默认移除
SecurityManager支持,SerializablePermission实际已基本弃用
保护变量反序列化的实用做法
若目标是防止敏感变量被反序列化还原或篡改,应组合使用以下技术:
-
声明为
transient:对密码、令牌、连接句柄等不需持久化的字段加该修饰符,JVM 自动跳过序列化/反序列化 -
自定义
readObject()方法:在类中重写该私有方法,在反序列化后立即清空或重置敏感字段(例如this.token = null;) -
使用反序列化过滤器限定类集:例如只允许
com.myapp.dto.**下的类,拒绝org.apache.commons.collections等高危包 -
避免实现
Serializable的敏感类:如凭证类、配置类、线程上下文类,优先用 JSON/Map 手动序列化,绕过原生机制
为什么别依赖 SerializablePermission 做变量防护
它的设计目标不是数据内容治理,而是沙箱环境下的“行为授权”。就像给某人发一张“可以进档案室”的通行证,并不等于你同时审核了他从档案室里拿出来的每一页纸的内容。反序列化安全的关键动作发生在字节流解析阶段,而 SerializablePermission 在那之前就已完成它的使命——甚至可能根本没被触发(因为多数应用早已不启用 SecurityManager)。

















