如何使用 JAXB2.0 禁用 DTD 获取

Posted

技术标签:

【中文标题】如何使用 JAXB2.0 禁用 DTD 获取【英文标题】:How to disable DTD fetching using JAXB2.0 【发布时间】:2012-04-12 03:51:19 【问题描述】:

我正在尝试使用 JAXB 来解组我最初使用 xjc 创建的一些 XML。我不想对解组进行任何验证,但是即使我根据 JAXB 文档使用 u.setSchema(null); 禁用了验证,但这并没有阻止 FileNotFoundException 在尝试运行时抛出并且可以'找不到架构。

JAXBContext jc = JAXBContext.newInstance("blast");
Unmarshaller u = jc.createUnmarshaller();
u.setSchema(null);
return u.unmarshal(blast)

我已经看到类似的问题,通过将 apache 属性 http://apache.org/xml/features/validation/schema 设置为 false 来从验证中禁用 SAX 解析,但我无法让 Unmarshaller 使用我自己的 sax 解析器。

【问题讨论】:

【参考方案1】:

根据@blaise-doughan 和@aerobiotic 的回答,这里有一个对我有用的解决方案:

import java.io.FileReader;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

public class Demo2 

    public static void main(String[] args) throws Exception 

        JAXBContext jc = JAXBContext.newInstance(MyBean.class);

        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        spf.setFeature("http://xml.org/sax/features/validation", false);

        XMLReader xmlReader = spf.newSAXParser().getXMLReader();
        InputSource inputSource = new InputSource(
                new FileReader("myfile.xml"));
        SAXSource source = new SAXSource(xmlReader, inputSource);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        MyBean foo = (MyBean) unmarshaller.unmarshal(source);
    

【讨论】:

这对我有用。另外还添加了spf.setValidating(false);谢谢【参考方案2】:

下面的示例代码演示了如何获得 JAXB (JSR-222) 实现以使用您的 SAX 解析器:

import java.io.FileReader;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

public class Demo 

    public static void main(String[] args) throws Exception 
        JAXBContext jc = JAXBContext.newInstance(Foo.class);

        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        XMLReader xmlReader = spf.newSAXParser().getXMLReader();
        InputSource inputSource = new InputSource(new FileReader("input.xml"));
        SAXSource source = new SAXSource(xmlReader, inputSource);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Foo foo = (Foo) unmarshaller.unmarshal(source);
        System.out.println(foo.getValue());
    


【讨论】:

这对我不起作用,但这些对我有用:parser.setFeature("apache.org/xml/features/nonvalidating/load-external-dtd", false); parser.setFeature("xml.org/sax/features/validation", false); This 网站解释了如何在任何主要的 Java 框架上阻止它。 似乎 FEATURE_SECURE_PROCESSING 是关于 entityExpansionLimit 的。查看文档的最后一部分docs.oracle.com/javase/1.5.0/docs/guide/xml/jaxp/… 这回答了“如何让 Unmarshaller 使用我自己的 sax 解析器”的问题,但没有回答“如何使用 JAXB2.0 禁用 DTD 获取”的问题。【参考方案3】:

回答“如何使用 JAXB2.0 禁用 DTD 获取”问题。

@sameer-puri 链接到https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#SAXTransformerFactory,它对问题的回答如下:

JAXB 解组器

由于 javax.xml.bind.Unmarshaller 解析 XML 并且不支持禁用 XXE 的任何标志,因此必须首先通过可配置的安全解析器解析不受信任的 XML,生成源对象作为结果,并传递源反对 Unmarshaller。例如:

//Disable XXE
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

//Do unmarshall operation
Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(),
                                new InputSource(new StringReader(xml)));
JAXBContext jc = JAXBContext.newInstance(Object.class);
Unmarshaller um = jc.createUnmarshaller();
um.unmarshal(xmlSource);

【讨论】:

【参考方案4】:

您可以直接从 javax.xml.transform.sax.SAXSource 创建 Unmarshaller。

查看此页面上的示例:http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/api/javax/xml/bind/Unmarshaller.html

比你“只”需要为那个 SAXSource 提供你自己的 URIResolver

【讨论】:

【参考方案5】:

以上建议对我没有任何帮助... 我建议这段代码对我有用☺️ 从 xml 中删除 Dtd ...使用正则表达式 字符串 str = event.getData(); str= str.replaceAll("^](?:]>[^])>"," ");

【讨论】:

【参考方案6】:

@doughan 和 @Renaud 的 SAXParserFactory 解决方案对我不起作用。由于错误

外部 DTD:无法读取外部 DTD“cXML.dtd”,因为 accessExternalDTD 属性设置的限制不允许“http”访问。

如果您使用公司代理,则以下解决方案有效。它基于XMLInputFactory

import java.io.FileReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import org.junit.Assert;

public class Demo3 

  public static void main(String[] args) throws Exception 

    JAXBContext jc = JAXBContext.newInstance(CXMLResponse.class);

    XMLInputFactory xif = XMLInputFactory.newFactory();
    xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
    XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("input.xml"));

    Unmarshaller unmarshaller = jc.createUnmarshaller();
    CXMLResponse parsedResponse = (CXMLResponse) unmarshaller.unmarshal(xsr);

    System.out.println(parsedResponse.toString());
  


灵感来自https://***.com/a/13069681/311420。再次感谢@bdoughan

【讨论】:

以上是关于如何使用 JAXB2.0 禁用 DTD 获取的主要内容,如果未能解决你的问题,请参考以下文章

XML,DTD:如何使顺序不重要

如何使字体真棒图标按钮的禁用状态?

添加文本和禁用滚动时如何使 UITextView 字段扩展?

Yii2:如何使用 jQuery 使 <div> 禁用/只读

如何从键盘获取 dtd 和 xml 文件?

如何使 UITableViewCell 显示为禁用?