java - 在 XmlValidatingMessageSelector 中关闭 DTD 加载和验证

标签 java spring-integration

如果 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)改变您的payloadDocument定制对象DocumentBuilderFactory .

看到我们无法影响 javax.xml.validation.Validator 的内部结构这一事实,我认为调用 convertToDocument() 是一个很好的妥协来自 validator 并将其包装到 DOMSource 。这样,确实,您的 DefaultXmlPayloadConverter会有效果。

请随意筹集 JIRA 甚至考虑贡献。

感谢您指出这一点!

关于java - 在 XmlValidatingMessageSelector 中关闭 DTD 加载和验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44812496/

相关文章:

java - Windows XP 阻止我的程序创建的 zip 文件

java - 部署子主题是否可以包含管理员的部署说明

java - Spring Integration 中的事务感知 POJO

具有双值的 Java MethodOverloading 错误

javascript - 为什么htmlunit的结果和chrome的结果不一样?

java - 使用ProceedingJoinPoint获取aspectj中的对象和变量

java - Spring Integration 中的外部消息传递

java - 发现 javax.mail.AuthenticationFailedException : failed to connect, 未指定密码?在收听密码正确的新邮件时

java - 我可以访问 http channel 入站适配器状态代码表达式中的 header 吗?

tcp - 我可以在扩展 Spring Integrations ByteArrayLengthHeaderSerializer 的类中推送消息吗?