4

因此,在我当前的项目中,我使用 JAXB RI 和 Sun 的 JRE(我相信是 Xerces)中的默认 Java 解析器来解组任意 XML。

首先我使用 XJC 编译一个如下形式的 XSD:

<?xml version="1.0" encoding="utf-8" ?> 
<xs:schema attributeFormDefault="unqualified" 
elementFormDefault="qualified" 
xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
<xs:element name="foobar">
...
</xs:element> 
</xs:schema>

在“好案例”中,一切都按设计进行。也就是说,如果我传递了符合此模式的 XML,那么 JAXB 会正确地将其解组为对象树。

当我通过外部 DTD 引用传递 XML 时,问题就出现了,例如

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foobar SYSTEM "http://blahblahblah/foobar.dtd">
<foobar></foobar>

在解组这样的事情时,SAX 解析器尝试加载远程实体(“ http://somehost/foobar.dtd ”),尽管这个片段显然不符合我之前用 XJC 编译的模式。

为了规避这种行为,因为我知道任何符合标准的 XML(根据我编译的 XSD)都不需要加载远程实体,所以我必须定义一个自定义 EntityResolver 来缩短所有远程实体的加载。所以不要做类似的事情:

MyClass foo = (MyClass) myJAXBContext.createUnmarshaller().unmarshal(myReader);

我被迫这样做:

XMLReader myXMLReader = mySAXParser.getXMLReader();
myXMLReader.setEntityResolver(myCustomEntityResolver);
SAXSource mySAXSource = new SAXSource(myXMLReader, new InputSource(myReader));
MyClass foo = (MyClass) myJAXBContext.createUnmarshaller().unmarshal(mySAXSource);

所以我的最终问题是:

当使用 JAXB 解组时,如果在没有加载这些远程实体的情况下可以将相关 XML 识别为无效时,底层 SAX 解析器加载远程实体是否应该自动短路?

另外,这似乎不是一个安全问题吗?鉴于 JAX-WS 在底层依赖 JAXB,似乎我可以将特制的 XML 传递给任何基于 JAX-WS 的 Web 服务,并导致 WS 主机加载任意 URL。

我是一个相对新手,所以我可能缺少一些东西。如果是这样,请告诉我!

4

1 回答 1

4

一个精心设计的问题,它值得一个答案:)

需要注意的一些事项:

  1. JAXB 运行时不依赖于 XML Schema。它使用 SAX 解析器生成 SAX 事件流,用于绑定到对象模型。此对象模型可以是手写的,也可以使用 XJC 从模式生成,但绑定和运行时彼此非常不同。因此,您可能知道良好的 XML 输入在运行时符合模式,但 JAXB 不符合。
  2. 强制运行时加载远程 DTD 引用并不构成安全漏洞。如果最后有一个真正的 DTD,最坏的情况是它不会验证。如果它不是真正的 DTD,那么它将被忽略。
  3. DTD 被认为是过时的,因此在高级 JAXB API 中没有直接支持它。如果您需要EntityResolver,则需要深入研究您已经完成的 SAX API。
  4. 如果您的类模型是从 XML 模式生成的,那么您应该考虑在运行时使用SchemaFactory和对其进行验证Unmarshaller.setSchema()。这将指示 Xerces 在传递给 JAXB 之前针对模式验证 SAX 事件。这不会阻止 DTD 被获取,但它增加了一层安全性,您知道数据是好的。
于 2009-10-28T23:06:31.777 回答