JEP 185: Restrict Fetching of External XML Resources | 限制获取外部 XML 资源
摘要
增强 JAXP API,以添加限制可用于获取外部资源的网络协议集的能力。
目标
定义标准属性以限制可用于获取外部资源的网络协议集。新属性应与现有的安全处理功能以及其他现有功能和属性无缝协作。
非目标
本提案专注于处理外部资源。不打算重塑现有的安全架构,也不打算更改已由实现支持但 API 中未指定的功能和属性。
动机
JAXP 的 安全处理功能 对 XML 处理器设置资源限制,以应对某些类型的拒绝服务攻击。然而,它并未限制获取外部资源的手段,这在尝试安全处理 XML 文档时也很有用。当前的 JAXP 实现支持可用于强制实施此类限制的实现特定属性,但需要一个标准的方法来完成此操作。
描述
JAXP 1.5 添加了三个新的 API 级别属性,以将外部连接限制为特定的命名协议:
javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD
:可通过其访问外部 DTD 和外部实体引用的协议列表。javax.xml.XMLConstants.ACCESS_EXTERNAL_SCHEMA
:可通过其解析由import
和include
元素的schemaLocation
属性指定的外部架构引用的协议列表。javax.xml.XMLConstants.ACCESS_EXTERNAL_STYLESHEET
:可通过其解析在样式表构造(如处理指令、document()
函数、import
元素和include
元素)中指定的外部引用的协议列表。
它还添加了三个相应的系统属性,为开发人员提供无需更改代码即可更改设置的能力:
javax.xml.accessExternalDTD
对应于ACCESS_EXTERNAL_DTD
javax.xml.accessExternalSchema
对应于ACCESS_EXTERNAL_SCHEMA
javax.xml.accessExternalStylesheet
对应于ACCESS_EXTERNAL_STYLESHEET
最后,它允许在现有的配置文件 ${java.home}/lib/jaxp.properties
中设置上述属性,以便为 JDK 或 JRE 的所有调用定义行为。文件中条目的格式为 property-name=value
,例如:
javax.xml.accessExternalDTD=file,http
属性值
上述任何属性的值都是一个协议列表,用逗号分隔。协议 是 URI 的方案部分,或者在 JAR 协议的情况下,是 jar
加上用冒号分隔的方案部分。方案的语法为:
scheme = alpha *( alpha | digit | "+" | "-" | "." )
where alpha = a-z and A-Z.
JAR 协议的语法为:
jar[:scheme]
包含关键字 jar
的协议不区分大小写。值中由 Character.isSpaceChar()
定义的任何空白都会被忽略。协议的示例包括 file
、http
和 jar:file
。
默认值:是否默认限制连接是实现选择。选项包括:
- 空字符串表示不允许访问;
- 特定协议(如
file
)表示仅允许通过该协议进行访问; - 关键字
all
表示允许通过所有协议进行访问。
当启用 FEATURE_SECURE_PROCESSING
时,建议实现默认限制外部连接,但这可能会为处理具有外部引用的 XML/XSD/XSL 的应用程序带来问题。
授予所有访问权限:关键字 all
授予使用所有协议的权限。例如,在 jaxp.properties
文件中设置 jdk.xml.accessExternalDTD=all
将允许系统像以前一样工作,不对如何获取外部资源施加任何限制。
通过 JAXP API 设置属性
可以通过 JAXP 工厂以如下方式设置 JAXP 属性:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setAttribute(name, value);
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
parser.setProperty(name, value);
XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(name, value);
SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage);
schemaFactory.setProperty(name, value);
TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(name, value);
范围和顺序
javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING
是包括 DOM、SAX、Schema 验证、XSLT 和 XPath 在内的 XML 处理器所需的一个特性。建议实现将与安全性相关的特性和属性与该特性相关联。当安全特性设置为 true 时,它要求实现将 XML 处理限制在实现限制之内。当设置为 false 时,它指示实现不受限制地处理 XML。对于 JAXP 1.5 中引入的新属性,建议当安全特性设置为 true 时,实现应限制外部连接;当设置为 false 时,允许完全访问。
jaxp.properties
文件中指定的属性会影响 JDK 或 JRE 的所有调用,并将覆盖默认值或可能已通过 FEATURE_SECURE_PROCESSING
设置的值。
系统属性(当设置时)将仅影响一次调用,并将覆盖默认设置或 jaxp.properties
中设置的值,或可能已通过 FEATURE_SECURE_PROCESSING
设置的值。
通过 JAXP 工厂或 SAXParser
API 指定的 JAXP 属性将覆盖系统属性、jaxp.properties
文件以及 FEATURE_SECURE_PROCESSING
的设置。
在以下情况下,新的 JAXP 属性将不会对它们试图限制的构造产生任何影响:
当在 SAX 或 DOM 解析器上设置了实体解析器,在 StAX 解析器上设置了 XML 解析器,或在转换器上设置了
URIResolver
时。当通过
SchemaFactory.newSchema()
方法显式创建模式时。当不需要外部资源时。例如,参考实现支持以下特性和属性,并可以按如下方式设置,以指示处理器不加载外部 DTD 或解析外部实体。
http://apache.org/xml/features/disallow-doctype-decl true http://apache.org/xml/features/nonvalidating/load-external-dtd false http://xml.org/sax/features/external-general-entities false http://xml.org/sax/features/external-parameter-entities false
测试
将添加新的测试以测试每个场景。同时,还将发布 JAXP TCK 的新版本。
需要进行大量测试以评估是否可以将 JDK 配置为默认限制连接。
风险和假设
JAXP 1.5 规范未指定属性的默认值。由于兼容性影响和风险,JAXP 1.5 将最初与默认配置集成,不限制连接。
JAXP 1.5 规范要求在将 FEATURE_SECURE_PROCESSING 明确设置为 true 时,必须设置新属性以限制外部连接。设置 FEATURE_SECURE_PROCESSING 的应用程序可能会注意到不兼容的行为,因此可能需要设置新的 JAXP 属性以覆盖 FEATURE_SECURE_PROCESSING。
影响
其他 JDK 组件:JAX-WS 直接受到影响。JAX-WS 需要使用新属性来确定是否要解析外部资源。根据我们的调查以及与其他 JDK 组件所有者的讨论,没有其他组件直接受到影响。
兼容性:规范对兼容性没有影响。是否通过设置默认值来限制或不限制来保持兼容性,取决于实现。
I18n/L10n:需要翻译几条新的错误消息。
TCK:需要创建 JAXP TCK 的新版本。