我有一个用于签署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中是否有任何导致此错误的更改?
答案 0 :(得分:35)
这里的问题相同。由于演变,似乎是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演变(请参阅changelog),因此他们必须在工作时 更改其他内容这种演变。
我们通过向javax.xml.crypto.URIDereferencer
提供自定义javax.xml.crypto.dom.DOMCryptoContext.setURIDereferencer(URIDereferencer)
来解决此问题,该自定义document.getElementById(...)
能够解析尚未存在于DOM文档树中的节点(XMLObject中的片段)。
我现在正在向Oracle报告此问题,我将使用错误ID更新答案。
编辑:在apache SVN
中找到了此信息编辑2:感谢this bug report我明白这是XML“Id”属性处理的演变。
以前版本的java / JSR-105 / SANTUARIO曾对descendant-or-self::*/@Id
中使用的“Id”属性非常宽容,但这个新版本需要一个标识为 ID XML的属性请讲。我的意思是命名属性“Id”或“ID”不再足够,您需要将其标记为ID,最终通过XSD / DTD架构验证。
不幸的是,我正在遵循一个无效的架构,因此无法通过Java解析。
如果您处于相同的情况,请参阅下面的解决方案。否则,如果您的XML文档确实具有有效的架构,请查看@sherb解决方案https://stackoverflow.com/a/17437919/233906
幸运的是,您可以使用Element.setIdAttributeNode(org.w3c.dom.Attr,boolean)
等方法将属性标记作为ID。
结合使用像Attr
这样的小XPath来获取((Element)attr.getOwnerElement()).setIdAttributeNode(attr,true)
“Id”节点加上一点Java setIdAttributeXXX()
可以让你摆脱困境。
但请注意: clone
仅适用于当前文档&节点。如果您adopt
/ import
/ setIdAttributeXXX()
,您需要在每个DOM树的新节点上执行{{1}}
答案 1 :(得分:10)
我也发现对这个问题的回答很有帮助,但我的解决方案有点不同。我正在使用OpenSAML 2.6.0,并在解析传入文档之前为DocumentBuilderFactory分配模式,通过正确标记ID属性解决了ResourceResolverException: Cannot resolve element with 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);
答案 2 :(得分:7)
我的代码遇到了同样的问题:
element.setAttributeNS(null, "Id", elementID);
FIX:指定ID
element.setAttributeNS(null, "Id", elementID);
Attr idAttr = element.getAttributeNode("Id");
element.setIdAttributeNode(idAttr, true);
答案 3 :(得分:3)
我遇到了同样的问题,并且还跟踪了Cerber提到的代码片段。 我很好奇这是一个错误还是故意改变。
使用此主题中给出的信息 Java XML DOM: how are id Attributes special? 我能够让事情重新恢复工作。
简而言之,'ID'属性必须是'xs:ID'类型(而不是'xs:string'),Dereferencer才能找到它。另请注意,根据您对DocumentBuilderFactory的使用,必须设置XML架构。
答案 4 :(得分:1)
如果你有
dsObjectChild.setAttribute("Id", "My-id-value");
将其更改为
dsObjectChild.setAttribute("Id", "My-id-value");
dsObjectChild.setIdAttribute("Id", true);
它正在使用java 1.7.0_45
答案 5 :(得分:0)
仅当ID设置为随机UUID [guidForSignature ="_" + UUID.randomUUID().toString();
]并且在运行时触发并发请求时(Java 1.8),我才面临同样的问题。
我尝试过如下设置ID属性,这对我没有帮助。但是,将ID属性设置为所有请求的常量ID值可解决问题。
Element element1= doc.getDocumentElement().setIdAttribute("ID", true);
OR
Element e1 =(Element)doc.getElementsByTagName("Assertion").item(0);
e1.setIdAttribute("ID", true);