如果 Spring Integration 中传入的 XML 中存在 !DOCTYPE
部分,如何阻止 XmlValidatingMessageSelector
中的 DTD 加载(和验证)?
更新
实际上,在我们的 SI 配置中,我们有这个过滤器配置
@Bean
public MessageSelector cageXmlValidator() {
XmlValidatingMessageSelector selector = new XmlValidatingMessageSelector(
new ClassPathResource("/CageMessage.xsd"),
XmlValidatingMessageSelector.SchemaType.XML_SCHEMA);
selector.setThrowExceptionOnRejection(true);
return selector;
}
并以这种方式在我们的流程中使用它
@Bean
public IntegrationFlow processorFlow(
...
MessageSelector cageXmlValidator,
Unmarshaller cageXmlUnmarshaller,
...) {
return IntegrationFlows
.from(cageInputChannel())
...
.filter(cageXmlValidator)
.transform(new UnmarshallingTransformer(cageXmlUnmarshaller))
...
.channel(cageOutputChannel())
.get();
}
我也尝试了这个 XmlValidatingMessageSelector
定义,但它不起作用
@Bean
public MessageSelector cageXmlValidator() throws Exception {
XmlValidatingMessageSelector selector = new XmlValidatingMessageSelector(
new ClassPathResource("/CageMessage.xsd"),
XmlValidatingMessageSelector.SchemaType.XML_SCHEMA);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
selector.setConverter(new DefaultXmlPayloadConverter(factory));
selector.setThrowExceptionOnRejection(true);
return selector;
}
最佳答案
我有一个测试用例,例如:
@Test
public void testValidMessage() throws Exception {
Document doc = XmlTestUtil.getDocumentForString("<!DOCTYPE greeting SYSTEM \"greeting.dtd\"><greeting>hello</greeting>");
GenericMessage<Document> docMessage = new GenericMessage<Document>(doc);
PollableChannel validChannel = ac.getBean("validOutputChannel", PollableChannel.class);
MessageChannel inputChannel = ac.getBean("inputChannelA", MessageChannel.class);
inputChannel.send(docMessage);
assertNotNull(validChannel.receive(100));
}
关注!DOCTYPE
MXL 代码段中的声明。
那个XmlTestUtil.getDocumentForString()
有这个代码:
DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();
builder.setNamespaceAware(true);
builder.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
return builder.newDocumentBuilder().parse(
new InputSource(new StringReader(strDoc)));
最新load-external-dtd
功能正是我所需要的。
因此,您在应用程序中需要考虑构建 Document
在验证之前提前获取您的 XML 并使用这些功能 DocumentBuilderFactory
.
更新
插入定制的DefaultXmlPayloadConverter
具有适当的DocumentBuilderFactory
对我们的有效负载没有影响:
validationExceptions = this.xmlValidator.validate(this.converter.convertToSource(message.getPayload()));
那convertToSource()
看起来像:
public Source convertToSource(Object object) {
Source source = null;
if (object instanceof Source) {
source = (Source) object;
}
else if (object instanceof Document) {
source = new DOMSource((Document) object);
}
else if (object instanceof String) {
source = new StringSource((String) object);
}
else {
throw new MessagingException("unsupported payload type [" + object.getClass().getName() + "]");
}
return source;
}
如你所见,没有人这么称呼 DocumentBuilderFactory
.
我建议你有一个.transform()
预付.filter(cageXmlValidator)
改变您的payload
到Document
定制对象DocumentBuilderFactory
.
看到我们无法影响 javax.xml.validation.Validator
的内部结构这一事实,我认为调用 convertToDocument()
是一个很好的妥协来自 validator 并将其包装到 DOMSource
。这样,确实,您的 DefaultXmlPayloadConverter
会有效果。
请随意筹集 JIRA 甚至考虑贡献。
感谢您指出这一点!
关于java - 在 XmlValidatingMessageSelector 中关闭 DTD 加载和验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44812496/