升级到 java7u25 后出现 XML dig sig 错误溶液

2022-09-02 00:14:16

我有一个用于对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 中是否有任何更改会导致此错误?


答案 1

同样的问题在这里。似乎是由于演变而在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引用java 7u25在XML Sig验证上的进化(参见changelog),所以他们在进行这种演变时一定已经破坏了其他东西

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

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


编辑:apache SVN中找到这个


编辑 2 :多亏了这个错误报告,我明白这是XML“Id”属性处理的演变。

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

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

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

溶液

幸运的是,您可以使用Element.setIdAttributeNode(org.w3c.dom.Attr,boolean)等方法将属性标记为ID。

结合一点XPath,比如获取“Id”节点加上一点Java,应该会让你摆脱麻烦。descendant-or-self::*/@IdAttr((Element)attr.getOwnerElement()).setIdAttributeNode(attr,true)

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


答案 2

我也发现对这个问题的回答很有帮助,但我的解决方案有点不同。我正在使用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);

推荐