Spring RestTemplate 无法解组包含“<!DOCTYPE ... dtd>"的 XML [英] Spring RestTemplate cannot unmarshal XML containing "<!DOCTYPE ... dtd>"

查看:90
本文介绍了Spring RestTemplate 无法解组包含“<!DOCTYPE ... dtd>"的 XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我调用了第三方提供的旧网络服务.我正在使用 Spring RestTemplate:

I call an old web service provided by a third party. I am using Spring RestTemplate:

HttpEntity<MyRequest> requestHttpEntity = new HttpEntity<>(requestBody, headers);
MyResponse response = restTemplate.postForEntity(url, requestHttpEntity, MyResponse.class);

我收到一个 XML(我无法影响的格式,它是第三方服务)作为响应:

I receive an XML (which format I cannot influence, it's a third party service) as a response:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE MyResponse SYSTEM "http://example.com:8080/some/path/MyResponse.dtd">

<MyResponse>
    ...
</MyResponse>

postForEntity() 方法抛出异常

org.springframework.web.client.RestClientException: 
    Error while extracting response for type [class com.example.MyResponse] and content type [text/xml;charset=ISO-8859-1];
nested exception is org.springframework.http.converter.HttpMessageNotReadableException: 
    Could not unmarshal to [class com.example.MyResponse]: null;
nested exception is javax.xml.bind.UnmarshalException

- with linked exception:
     [org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 10;
     DOCTYPE is disallowed when the feature
     "http://apache.org/xml/features/disallow-doctype-decl" set to true.]

我在这里找到了对 http://apache.org/xml/features/disallow-doctype-decl 功能的唯一合理参考:https://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl

I found the only sensible reference to the http://apache.org/xml/features/disallow-doctype-decl feature here: https://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl

问题:如何在不完全避免 Spring RestTemplate 的自动魔术行为的情况下自定义解组?我想强制解组器接受包含带有 DTD 引用的元素的 XML.

Question: How can I customize the unmarshaling without completely avoiding the automagic behavior of Spring RestTemplate? I want to force the unmarshaler to accept XML containing element with DTD reference.

这个问题与我的另一个问题密切相关 如何在 Spring RestTemplate 中自定义自动封送处理以生成/修改 XML 标头(编码、DOCTYPE),但那里提出的解决方案在这里并不容易适用.

This question is strongly related to my other question How to customize automatic marshaling in Spring RestTemplate to produce/modify XML headers (encoding, DOCTYPE), but the solution proposed there is not easily applicable here.

推荐答案

默认情况下 Jaxb2RootElementHttpMessageConverter 禁用 DTD 支持(以及该 XML 实体支持).这样做的原因是它具有安全隐患,请参阅 SPR-11376.

要在 Jaxb2RootElementHttpMessageConverter 上启用它,您可以将 supportDtd 属性设置为 true 以再次启用它.但请注意,这也会带来一些潜在的安全问题!

To enable it on the Jaxb2RootElementHttpMessageConverter you can set the supportDtd property to true to enable it again. But be aware this will also open up some potential security issues!.

@Bean
public Jaxb2RootElementHttpMessageConverter jaxb2RootElementHttpMessageConverter() {
    Jaxb2RootElementHttpMessageConverter converter = new Jaxb2RootElementHttpMessageConverter();
    converter.setSupportDtd(true);
    return converter;
}

这应该足以(重新)配置支持,而无需添加任何额外的配置.要记住的一件事是,这将配置全局可用的 Jaxb2RootElementHttpMessageConverter,因此将影响您可能想要使用的所有控制器和 RestTemplate.

This should be enough to (re)configure support without needing to add any additional configuration. One thing to remember is that this will configure the globally available Jaxb2RootElementHttpMessageConverter and as such will impact all controllers and RestTemplates you might want to use.

除了这样做之外,您还可以使用 RestTemplateBuilder,您应该在创建 RestTemplate 的实例时使用它来仅影响该特定的 RestTemplate>.

Instead of doing this you could also use the RestTemplateBuilder which you should use when creating an instance of the RestTemplate to only influence that specific RestTemplate.

@Bean
public RestTemplate yourRestTemplate(RestTemplateBuilder builder) {
    Jaxb2RootElementHttpMessageConverter converter = new Jaxb2RootElementHttpMessageConverter();
    converter.setSupportDtd(true);

    return builder.messageConverters(converter).build()
}

通过这种方式,您可以针对 RestTemplate 的那个实例配置它并配置您喜欢的内容.

This way you can configure it specific for that instance of the RestTemplate and configure what you like.

这篇关于Spring RestTemplate 无法解组包含“&lt;!DOCTYPE ... dtd&gt;"的 XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆