FEATURE_SECURE_PROCESSING设为false不生效的解决方法咨询
调用setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false)后取值仍为true,不是代码写法错误,是JDK内置JAXP实现的强制安全规则:
从JDK 8u202、JDK 11及之后的所有版本,内置的DocumentBuilderFactory、SAXParserFactory、TransformerFactory等XML解析组件,都将FEATURE_SECURE_PROCESSING设为强制开启的只读特性,代码层面调用setFeature传入false会被直接忽略,和你查到的文档描述完全一致:
TransformerFactory可对外暴露某特性的取值,但无法更改该特性的状态。
这个规则是JDK内置XML组件的统一安全策略,并非只针对TransformerFactory生效。
完全不推荐用反射绕过该限制,没有任何稳定性可言:
- 不同JDK版本、不同发行版(OpenJDK、Corretto、Dragonwell等)的JAXP内部实现类不同,存储特性值的字段名、字段结构没有统一规范,反射代码在某一个小版本能正常运行,换个环境就会抛出字段不存在的异常
- JDK 16及以上版本默认开启模块访问限制,反射修改核心模块内部字段会直接抛出
InaccessibleObjectException,就算添加JVM参数放开限制,也可能被后续JDK的安全更新随时封堵 - 反射修改内部状态可能触发JVM安全管理器校验,在配置了安全策略的环境里会直接被拦截
首先明确:绝大多数场景下不需要关闭FEATURE_SECURE_PROCESSING。这个特性开启后只会默认限制XML解析的外部实体访问、设置解析的内存/CPU占用阈值防止DoS攻击,你代码里已经手动将ACCESS_EXTERNAL_DTD、ACCESS_EXTERNAL_SCHEMA设为空字符串完成了XXE防护,常规XML解析逻辑不会受该特性开启的影响。
如果确实有特殊业务需求(比如需要解析超大规模XML、使用被安全模式禁用的特定XML特性),只有两种官方支持的稳定方案:
- 方案1:通过JVM启动参数全局关闭该特性,启动时添加参数:
-Djdk.xml.secureProcessing=false
该参数是JDK官方暴露的配置项,跨小版本兼容性有保障,配置后内置JAXP实现会读取该配置决定是否开启安全处理。
- 方案2:替换XML解析实现为独立的Apache Xerces2版本,不使用JDK内置的JAXP实现。独立发行的Xerces2没有强制锁死
FEATURE_SECURE_PROCESSING特性,调用setFeature传入false可以正常生效。
内容的提问来源于stack exchange,提问作者Matthew

