Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java DOM appendChild:名称空间和签名文档_Java_Xml_Jaxb_Xml Dsig - Fatal编程技术网

Java DOM appendChild:名称空间和签名文档

Java DOM appendChild:名称空间和签名文档,java,xml,jaxb,xml-dsig,Java,Xml,Jaxb,Xml Dsig,生成带有签名节点的文档时遇到问题。我有一堆签名的XML,是文本格式的。他们的签名是有效的,我已经用xmlsec1测试过了。我必须加载所有XML并将它们放在另一个XML文档中,以便将其发送到另一个服务。 因此,首先我创建容器文档(“sobre”是一个局部变量,一个JAXB根元素): 然后我将XML添加到容器中: for (String cfexml : cfexmls) { Document cfe = loadXMLFromString(cfexml); Node newNode = d

生成带有签名节点的文档时遇到问题。我有一堆签名的XML,是文本格式的。他们的签名是有效的,我已经用xmlsec1测试过了。我必须加载所有XML并将它们放在另一个XML文档中,以便将其发送到另一个服务。 因此,首先我创建容器文档(“sobre”是一个局部变量,一个JAXB根元素):

然后我将XML添加到容器中:

for (String cfexml : cfexmls) {
  Document cfe = loadXMLFromString(cfexml);
  Node newNode = doc.importNode(cfe.getDocumentElement(), true);
  doc.getElementsByTagName("EnvioCFE").item(0).appendChild(newNode);
}
最后,我从容器文档中获取xml:

TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
StringWriter outputWriter = new StringWriter();
trans.transform(new DOMSource(doc), new StreamResult(outputWriter));
String signedxml = outputWriter.toString();
关键是我正在修改子节点,没有名称空间,因此提取节点的签名验证失败。下面是我必须添加为子节点的XML摘录:

<?xml version="1.0" encoding="UTF-8"?>
<CFE xmlns="http://org.importe.test" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" xmlns:ns3="http://www.w3.org/2001/04/xmlenc#" version="1.0">
  <data>
    [...]
  </data>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    [...]
  </Signature>
</CFE>

好的,我做了研究,发现了问题:

  • 如果我使用xalan-2.7.1.jar、xercesImpl-2.9.1.jar、xml-api-1.3.04.jar和xmlsec-1.5.6.jar实现DOM和xml安全性,它的工作原理与我预期的一样:添加节点不会修改内容,因此数字签名是有效的
  • 如果我使用标准java库,不仅是添加节点更改节点本身,而且有时数字签名没有通过xmlsec1检查,我认为从DOM到字符串的转换会出现问题
我希望这能帮助一些人,反正我不知道为什么会这样,我肯定我没有做奇怪的事情,但我现在没有时间深入研究


实际上,我一直在寻找如何告诉glassfish加载我想要的DOM实现,或者设置优先级:我没有找到说“加载xerces而不是标准库”的方法。

您能显示
loadXMLFromString
的代码吗?我怀疑问题就在那里。特别是如果您使用的是DocumentBuilderFactory,那么默认情况下它不支持名称空间,您需要在创建DocumentBuilder之前调用setter来打开名称空间。当然,请参阅我的编辑(正如您所看到的,我使用的是setNamespaceAware)。嗯,我现在明白您的意思了。XML序列化程序从CFE元素中省略这三个名称空间声明是正确的,因为它们已经在其父元素上生效。我不知道有什么办法可以推翻这一点。我想您可以尝试在故意关闭名称空间的情况下构建DOM树,以便名称空间声明仅被视为属性。不过,如果这样做,您可能需要切换到使用DomImplementals进行序列化,而不是使用转换器,我不确定XSLT工具能否很好地处理不支持名称空间的DOM。@IanRoberts你说:“你可以尝试在故意关闭名称空间的情况下构建DOM树”,我如何才能做到这一点?
<?xml version="1.0" encoding="UTF-8"?>
<CFE xmlns="http://org.importe.test" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" xmlns:ns3="http://www.w3.org/2001/04/xmlenc#" version="1.0">
  <data>
    [...]
  </data>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    [...]
  </Signature>
</CFE>
<?xml version="1.0" encoding="UTF-8"?>
<EnvioCFE xmlns="http://org.importe.test" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" xmlns:ns3="http://www.w3.org/2001/04/xmlenc#" version="1.0">
  <Header version="1.0">
  </Header>
  <CFE version="1.0">
    <data>
      [...]
    </data>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
      [...]
    </Signature>
  </CFE>
</EnvioCFE>
public Document loadXMLFromString(String xml) throws ParserConfigurationException, SAXException, IOException {
  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  factory.setNamespaceAware(true);
  DocumentBuilder builder = factory.newDocumentBuilder();
  return builder.parse(new InputSource(new StringReader(xml)));
}