22

我有一个用于签署 XML 文档的 Java 应用程序。将 Java 升级到最新版本 (Java7u25) 后,它停止工作。我收到以下错误:

javax.xml.crypto.dsig.XMLSignatureException:
javax.xml.crypto.URIReferenceException: 
com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException:
Cannot resolve element with ID ...

恢复到 java7u21 解决了这个问题。XML Dig Sig API 中是否有任何更改导致此错误?

4

6 回答 6

39

这里同样的问题。由于进化,似乎是 JVM 内部的一个错误。

我把它归结为com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment

在 java 7u21 及之前:

91: // Element selectedElem = doc.getElementById(id);
92: selectedElem = IdResolver.getElementById(doc, id);

在 java 7u25 中:

87: selectedElem = doc.getElementById(id);
    //...
93: if (secureValidation) {

secureValidation指的是 XML Sig 验证上的 java 7u25 演变(请参阅更改日志),因此他们在进行此演变时一定已经破坏 了其他内容

我们通过提供一个自定义javax.xml.crypto.URIDereferencer来解决这个问题,该自定义javax.xml.crypto.dom.DOMCryptoContext.setURIDereferencer(URIDereferencer)能够解析尚未在 DOM 文档树中的节点(XMLObject 中的片段)。

我现在正在向 Oracle 报告此问题,我将使用错误 ID 更新答案。


编辑:apache SVN中找到了这个


编辑 2:感谢这个错误报告,我了解到这是 XML“Id”属性处理的演变。

以前版本的 java/JSR-105/SANTUARIO 过去对使用的“Id”属性非常宽容,document.getElementById(...)但这个新版本需要一个被标识为ID XML 的属性。我的意思是命名属性“Id”或“ID”已经不够用了,您需要将其标记为 ID,最终通过 XSD/DTD 模式验证。

不幸的是,我正在遵循一个无效的模式,因此 Java 无法解析。

如果您处于相同情况,请参阅下面的解决方案。否则,如果您的 XML 文档确实具有有效的架构,请查看@sherb 解决方案https://stackoverflow.com/a/17437919/233906

解决方案

幸运的是,您可以使用诸如Element.setIdAttributeNode(org.w3c.dom.Attr,boolean).

结合一点 XPath,比如descendant-or-self::*/@Id获取Attr“Id”节点和一点 Java ((Element)attr.getOwnerElement()).setIdAttributeNode(attr,true),应该可以让您摆脱麻烦。

但要小心: setIdAttributeXXX()仅对当前文档和节点有效。clone//如果你需要在每个adoptDOM树的新节点上做一个importsetIdAttributeXXX()

于 2013-06-27T15:41:25.093 回答
10

我还发现对这个问题的回答很有帮助,但我的解决方案有点不同。我正在使用 OpenSAML 2.6.0,并在解析传入文档之前将架构分配给 DocumentBuilderFactory,ResourceResolverException: Cannot resolve element with ID...通过正确标记 ID 属性来解决异常。这是一个例子:

InputStream in = new ByteArrayInputStream(assertion.getBytes());       
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(new URL("http://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd"));
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setSchema(schema);
Document document = factory.newDocumentBuilder().parse(in);
于 2013-07-03T00:31:03.007 回答
8

我对代码有同样的问题:

element.setAttributeNS(null, "Id", elementID);

修复: 指定 id

element.setAttributeNS(null, "Id", elementID);
Attr idAttr = element.getAttributeNode("Id");
element.setIdAttributeNode(idAttr, true);
于 2013-09-11T15:30:58.950 回答
3

我遇到了同样的问题,并将其追踪到 Cerber 提到的代码片段。我很好奇这是一个错误还是故意做出的改变。

有了这个线程 Java XML DOM 中给出的信息:id 属性有什么特别之处? 我能够让事情重新开始工作。

简而言之,“ID”属性必须是“xs:ID”类型(而不是“xs:string”),以便解引用器找到它。另请注意,根据您对 DocumentBuilderFactory 的使用,必须设置 XML 模式。

于 2013-06-28T12:49:31.043 回答
2

如果你有

dsObjectChild.setAttribute("Id", "My-id-value");

将其更改为

dsObjectChild.setAttribute("Id", "My-id-value");
dsObjectChild.setIdAttribute("Id", true);

它正在使用 java 1.7.0_45

于 2014-04-01T22:53:37.927 回答
0

guidForSignature ="_" + UUID.randomUUID().toString();仅当使用随机 UUID [ ] 设置 ID 并且在运行时触发并发请求时(Java 1.8),我才会面临同样的问题。

我尝试设置 ID 属性,如下所示,但对我没有帮助。但是,将所有请求的 ID 属性设置为常量 ID 值解决了该问题。

Element element1= doc.getDocumentElement().setIdAttribute("ID", true);

或者

Element e1 =(Element)doc.getElementsByTagName("Assertion").item(0);
e1.setIdAttribute("ID", true);
于 2018-06-14T00:36:11.950 回答