如何使用Java的DocumentBuilder获取XML注释

问题描述 投票:0回答:1

我有一个使用SAML身份验证的应用程序,充当SP,因此解析SAMLResponses。我收到通知,告知与我的应用程序通信的IdP现在将开始使用http://www.w3.org/2001/10/xml-exc-c14n#WithComments签署他们的SAMLResponses,这意味着在计算SAML签名的有效性时注释很重要。

这就是问题所在 - 我用于XML解析的库默认剥离这些注释节点。看这个示例程序:

import org.apache.commons.io.IOUtils;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class Main {

    public static void main(String[] args) {
        try {
            String xml = "<NameID>test@email<!---->.com</NameID>";
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            documentBuilderFactory.setNamespaceAware(true);
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document doc = documentBuilder.parse(IOUtils.toInputStream(xml));
            NodeList nodes = doc.getElementsByTagName("NameID");

            if (nodes == null || nodes.getLength() == 0)
            {
                throw new RuntimeException("No NameID in document");
            }

            System.out.println(nodes.item(0).getTextContent());

        } catch(Exception e) {
            System.err.println(e.getMessage());
        }
    }
}

所以,这个程序将打印[email protected](这意味着我的SAML代码也将获得)。这是一个问题,因为我很确定它会导致签名验证在没有包含注释的情况下失败,因为XML文档是使用#WithComments规范化方法签名的。

有没有办法让DocumentBuilder / getTextContent()留在评论节点,所以我的签名不会被遗漏的评论无效?

getTextContent()的文档在这里:https://docs.oracle.com/javase/7/docs/api/org/w3c/dom/Node.html#getTextContent()

java xml saml
1个回答
1
投票

您的代码实际上保留了评论。

在这里,略有修改:

public static void main(String[] args) throws Exception {
    String xml = "<NameID>test@email<!--foobar-->.com</NameID>";
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    documentBuilderFactory.setNamespaceAware(true);
    DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
    Document doc = documentBuilder.parse(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)));
    NodeList childNodes = doc.getDocumentElement().getChildNodes();
    Node[] nodes = new Node[childNodes.getLength()];
    for (int index = 0; index < childNodes.getLength(); index++) {
        nodes[index] = childNodes.item(index);
    }
    System.out.println(nodes[1].getTextContent());
}

打印foobar。 (Run it on Ideone。)

根元素有3个子节点,其中一个是注释节点。所以它实际上是保留的。

© www.soinside.com 2019 - 2024. All rights reserved.