java – jaxb unmarshal在使用默认的sax解析器时可以使用精心制作的xml吗?
作者:互联网
所以在我当前的项目中,我使用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.
我是这个的相对新手,所以我可能会缺少一些东西.如果有,请告诉我!
解决方法:
一个精心设计的问题,它值得一个答案:)
有些事情需要注意:
> JAXB运行时不依赖于XML Schema.它使用SAX解析器生成一个SAX事件流,用于绑定到对象模型.此对象模型可以手写,也可以使用XJC从模式生成,但绑定和运行时彼此非常不同.因此,您可能知道良好的XML输入在运行时符合架构,但JAXB没有.
>强制运行时加载远程DTD引用不构成安全漏洞.如果最后有一个真正的DTD,最糟糕的情况是它不会验证.如果它不是真正的DTD,那么它将被忽略.
> DTD被认为是过时的,因此在高级JAXB API中没有直接支持它.如果您需要EntityResolver,则需要深入了解已经完成的SAX API.
>如果您的类模型是从XML Schema生成的,那么您应该考虑在运行时使用SchemaFactory和Unmarshaller.setSchema()对其进行验证.这将指示Xerces在传递给JAXB之前根据模式验证SAX事件.这不会阻止DTD被提取,但它会增加一层安全性,您知道数据是好的.
标签:java,jaxb,jax-ws,sax,xjc 来源: https://codeday.me/bug/20190627/1301396.html