所以在我当前的项目中,我使用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 &quot;)尽管这个片段显然不符合我之前用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。

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

有帮助吗?

解决方案

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

有些注意事项:

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