[英]Reference URI error creating digital signature for a specific XML element/ Node
我一直试图使它正常工作,但是当我尝试为XML文档中的特定元素创建数字标识时,我会遇到异常。 源文档是SOAP信封,程序会解析文件中的数据并创建Document对象。 基本上,我想做的是创建具有多个部分/引用的数字签名...主要是SOAP正文和SOAP Header的Security节点下的TimeStamp节点。 因此,现在我正在尝试对SOAP消息的主体部分进行签名。 SOAP主体具有wsu:Id值,并且在创建Reference对象时正在使用该值。 我正在使用securityNode参考来插入Signature节点,因为无论如何它应该在该位置。 我不认为这是个问题,但我想以防万一。 我想我做对了,但是没有用。 我看到其他人也发布了相同的问题,但没有给出答案。
我尝试了很多不同的事情,只要我指定用于创建Reference对象的URI,我就会得到异常。 奇怪的是,在对上下文进行签名时会引发异常。 我这样做对吗? 我该如何纠正? 任何帮助是极大的赞赏。
// * ** * ** * ** 例外 ** * ** * ** *
线程“主”中的异常javax.xml.crypto.dsig.XMLSignatureException:javax.xml.crypto.URIReferenceException:org.jcp.xml.dsig.internal.dom.DOMReference.dereference处的java.lang.NullPointerException(未知源) org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(未知源)位于org.jcp.xml.dsig.internal处的org.jcp.xml.dsig.internal.dom.DOMReference.digest(未知源)。 dom.DOMXMLSignature.sign(未知源),位于XMLDsigTester.main(XMLDsigTester.java:163)由以下原因引起:javax.xml.crypto.URIReferenceException:org.jcp.xml.dsig.internal.dom.DOMURIDereferencer .dereference(Unknown Source)... 5更多原因:com处com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverDirectHTTP.engineCanResolve(Unknown Source)处的java.lang.NullPointerException。 com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResol上的sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.canResolve(未知源) ver.getInstance(Unknown Source)...还有6个javax.xml.crypto.URIReferenceException:org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference处的java.lang.NullPointerException(org.jcp处)。 org.jcp.xml.dsig.internal.dom.DOMReference.digest(未知源)(位于org.jcp.xml.dsig.internal.dom.DOMXMLSignature中的xml.dsig.internal.dom.DOMReference.dereference(未知源))。 org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(XMLDsigTester.main(XMLDsigTester.java:163)处的digestReference(未知源)由com.sun.org处的java.lang.NullPointerException com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.canResolve(未知源)处的.apache.xml.internal.security.utils.resolver.implementations.ResolverDirectHTTP.engineCanResolve(未知源) .sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.getInstance(未知源)...还有6个
//******************** JAVA CLass ********************
import javax.xml.crypto.*;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dom.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.*;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.*;
import java.util.Collections;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.*;
public class XMLDsigTester
{
public static void main(String[] args) throws Exception
{
////////////// DECLARATIONS //////////////////
final String ENVELOPE_TAG = "Envelope";
final String HEADER_TAG = "Header";
final String SECURITY_TAG = "Security";
final String BODY_TAG = "Body";
final String SEPARATOR = ":";
Node envelopeNode = null;
Node headerNode = null;
Node bodyNode = null;
NodeList envelopeChildren = null;
NodeList headerChildren = null;
Node childNode = null;
Node securityNode = null;
String providerName = null;
String sEnvelopeNamespace = null;
String sFullHeaderTagName = null;
String sFullBodyTagName = null;
String sNodeName = null;
int iEnvelopeChildren;
int iHeaderChildren;
////////////// START OF LOGIC //////////////////
providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(new FileInputStream("myfile.xml"));
Provider providerObj = (Provider) Class.forName(providerName).newInstance();
/// Create references to the Envelope, Header, Body and Security nodes ///
envelopeNode = doc.getDocumentElement();
envelopeChildren = envelopeNode.getChildNodes();
iEnvelopeChildren = envelopeChildren.getLength();
sEnvelopeNamespace = envelopeNode.getPrefix();
if (sEnvelopeNamespace != null && !sEnvelopeNamespace.trim().equals(""))
{
sFullHeaderTagName = sEnvelopeNamespace.trim().concat(SEPARATOR).concat(HEADER_TAG);
sFullBodyTagName = sEnvelopeNamespace.trim().concat(SEPARATOR).concat(BODY_TAG);
}
else
{
sFullHeaderTagName = HEADER_TAG;
sFullBodyTagName = BODY_TAG;
}
for (int i=0; i < iEnvelopeChildren; i++)
{
sNodeName = null;
childNode = null;
childNode = envelopeChildren.item(i);
sNodeName = childNode.getNodeName().trim();
if (sNodeName.equalsIgnoreCase(sFullHeaderTagName))
headerNode = childNode;
else if (sNodeName.equalsIgnoreCase(sFullBodyTagName))
bodyNode = childNode;
}
headerChildren = headerNode.getChildNodes();
iHeaderChildren = headerChildren.getLength();
String sLocalNodeName = null;
for (int i=0; i < iHeaderChildren; i++)
{
sLocalNodeName = null;
sNodeName = null;
childNode = null;
childNode = headerChildren.item(i);
sNodeName = childNode.getNodeName().trim();
sLocalNodeName = childNode.getLocalName();
if (sLocalNodeName != null)
if (sLocalNodeName.trim().equalsIgnoreCase(SECURITY_TAG))
{
securityNode = childNode;
break;
}
}
/// Main logic for generating XML signature ///
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", providerObj);
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair kp = kpg.generateKeyPair();
KeyInfoFactory kif = fac.getKeyInfoFactory();
KeyValue kv = kif.newKeyValue(kp.getPublic());
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
DOMSignContext dsc = new DOMSignContext(kp.getPrivate(), securityNode);
dsc.putNamespacePrefix("http://www.w3.org/2000/09/xmldsig#", "ds");
DigestMethod digestMethod = fac.newDigestMethod(DigestMethod.SHA1, null);
Transform transformObj = fac.newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null);
Reference ref = fac.newReference("part-Body-4F4332715C4C1670E10080000A441E26", digestMethod, Collections.singletonList(transformObj), null, null);
CanonicalizationMethod canonMethodObj = fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null);
SignatureMethod signatureMethodObj = fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null);
SignedInfo si = fac.newSignedInfo(canonMethodObj, signatureMethodObj, Collections.singletonList(ref));
XMLSignature signature = fac.newXMLSignature(si, ki);
signature.sign(dsc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(doc), new StreamResult(new FileOutputStream("mySignedFile.xml")));
}
} <br>
//******************** INPUT DATA ********************
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Timestamp wsu:Id="ts-4F43326F5C4C1670E10080000A441E26">
<wsu:Created>2012-09-30T22:09:55Z</wsu:Created>
<wsu:Expires>2012-09-30T22:14:55Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
<wsa:Action soap-env:mustUnderstand="1" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"/>
<wsa:MessageID xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">uuid:4f43f2ff-38aa-1a90-e100-80000a441e26</wsa:MessageID>
</soap-env:Header>
<soap-env:Body wsu:Id="part-Body-4F4332715C4C1670E10080000A441E26" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<PurchaseOrder>
<Customer>
<Name>Robert Smith</Name>
<CustomerId>788335</CustomerId>
</Customer>
<Item partNum="C763">
<ProductId>6883-JF3</ProductId>
<Quantity>3</Quantity>
<ShipDate>2002-09-03</ShipDate>
<Name>ThinkPad X20</Name>
</Item>
</PurchaseOrder>
</soap-env:Body>
</soap-env:Envelope>
我希望还不算太晚:)。 我一直在用您的输入对您的代码进行一些测试。 您需要知道的第一件事是需要使用“ #nodeId”指定节点名称,在您的示例中,该名称应为“#part-Body-4F4332715C4C1670E10080000A441E26”(缺少“#”符号)。 下一个问题与“ wsu”名称空间中的“ Id”有关; 如果只是“ Id”而不是“ wsu:Id”,则您的代码将找到“ soap-env:Body”节点,但实际并非如此。 如果您可以添加其他“ Id”属性或修改示例中的示例,删除“ wsu”名称空间前缀,则说明您完成了。 如果不需要,则需要进行一些修改,添加一个转换,以便可以选择要签名的节点。 您应该替换行:
Transform transformObj = fac.newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null);
Reference ref = fac.newReference("part-Body-4F4332715C4C1670E10080000A441E26", digestMethod, Collections.singletonList(transformObj), null, null);
有:
List<Transform> transforms = new ArrayList<Transform>(2);
Map<String, String> namespaces = new HashMap<String, String>(1);
namespaces.put("soap-env", "http://schemas.xmlsoap.org/soap/envelope/");
XPathFilterParameterSpec paramsXpath = new XPathFilterParameterSpec("/soap-env:Envelope/soap-env:Body", namespaces);
transforms.add(fac.newTransform(Transform.XPATH, (TransformParameterSpec) paramsXpath));
Transform transformObj = fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null);
transforms.add(transformObj);
Reference ref = fac.newReference("", digestMethod, transforms, null, null);
在此新代码中,您向引用添加了一个转换,该转换使用XPath从您提供的xml输入中选择“ soap-env:Body”节点。 该节点将被签名并添加到“安全性”节点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.