我有rtfm但仍然有问题。我正在重读手册,但在这里发帖是因为我所做的不起作用。我得到了一个SOAP服务的xsd和wsdl文件。我从未实现过需要数字签名的客户端。我写了一个soaphandler来修改信封标题,但我无法弄清楚我做错了什么。
肥皂消费者告诉我,传入签名代的post canoncalization xml应如下所示:
<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"></ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"></ds:SignatureMethod>
<ds:Reference URI="#secinfo" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"></ds:DigestMethod>
<ds:DigestValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">ZwOJboUtw1RlDspibqbyaWrKIog=</ds:DigestValue>
<ds:Transforms xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:XPath xmlns:ds="http://www.w3.org/2000/09/xmldsig#">//*[@id='secinfo']/child::*/text()</ds:XPath>
</ds:Transform>
</ds:Transforms>
</ds:Reference>
</ds:SignedInfo>
我生成的xml看起来更像是这样:
<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
<ds:Reference URI="#secinfo">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>ZwOJboUtw1RlDspibqbyaWrKIog=</ds:DigestValue>
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
<ds:XPath>//*[@id='secinfo']/child::*/text()</ds:XPath>
</ds:Transform>
</ds:Transforms>
</ds:Reference>
</ds:SignedInfo>
我为处理邮件而编写的代码如下。根据我的理解,当我创建一个名为“ds”的SOAPElement和uri时,它应该如上所述正确表示。我试过addAttribute(“xmlns:ds”,“url”);对于某些元素,它仍然失败。
@Override
public boolean handleMessage(SOAPMessageContext context) {
try {
if (messageOutbound(context)) {
SOAPFactory factory = SOAPFactory.newInstance();
SOAPMessage soapMsg = context.getMessage();
SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
SOAPHeader soapHeader = soapEnv.getHeader();
// if no header, add one
if (soapHeader == null) {
soapHeader = soapEnv.addHeader();
}
String serverURI = "service.messages";
soapEnv.addNamespaceDeclaration("urn", serverURI);
String timeStamp = generateTimeStamp();
timeStamp = "201703221758";
//Create the XML headers via example
String prefix = "wsse";
String uri = "http://schemas.xmlsoap.org/ws/2002/04/secext";
SOAPElement security = factory.createElement("Security", prefix, uri);
uri = "http://www.w3.org/2000/09/xmldsig#";
SOAPElement signedInfo = factory.createElement("SignedInfo", "ds", uri);
SOAPElement canoncalized = factory.createElement("CanonicalizationMethod", "ds", uri);
canoncalized.setAttribute("Algorithm", "http://www.w3.org/2001/10/xml-exc-c14n#");
canoncalized.addNamespaceDeclaration("ds", uri);
SOAPElement signatureMethod = factory.createElement("SignatureMethod", "ds", uri);
signatureMethod.setAttribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#rsa-sha1");
SOAPElement reference = factory.createElement("Reference", "ds", uri);
reference.setAttribute("URI", "#secinfo");
SOAPElement digestMethod = factory.createElement("DigestMethod", "ds", uri);
digestMethod.setAttribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1");
// up to here is good
SOAPElement digestValue = factory.createElement("DigestValue", "ds", uri);
String userString = "USER=" + userID + ";CORR=" + corrNo + ";TIMESTAMP=" + timeStamp;
String digestVal = createDigest("sha1", userString);
digestValue.setValue(digestVal);
SOAPElement transforms = factory.createElement("Transforms", "ds", uri);
SOAPElement transform = factory.createElement("Transform", "ds", uri);
transform.setAttribute("Algorithm", "http://www.w3.org/TR/1999/REC-xpath-19991116");
SOAPElement xPath = factory.createElement("XPath", "ds", uri);
xPath.setValue("//*[@id='secinfo']/child::*/text()");
transform.addChildElement(xPath);
transforms.addChildElement(transform);
reference.addChildElement(digestMethod);
reference.addChildElement(digestValue);
reference.addChildElement(transforms);
signedInfo.addChildElement(canoncalized);
signedInfo.addChildElement(signatureMethod);
signedInfo.addChildElement(reference);
SOAPElement signature = factory.createElement("Signature", "ds", uri);
final StringWriter sw = new StringWriter();
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(signedInfo),
new StreamResult(sw));
String s = sw.toString();
s = s.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "");
System.out.println(s);
//need to inisitalize the canonvalue not sure how?
SOAPElement signatureValue = factory.createElement("SignatureValue", "ds", uri);
String canonValue = canonicalize(s);
signatureValue.setValue(createSignature("rsa-sha1", canonValue));
SOAPElement keyInfo = factory.createElement("KeyInfo", "ds", uri);
SOAPElement keyName = factory.createElement("KeyName", "ds", uri);
keyName.setValue("BLAHBLAHBLAH");
SOAPElement userNameToken = factory.createElement("UsernameToken", "t", "http://schemas.xmlsoap.org/ws/2002/04/secext");
userNameToken.setAttribute("id", "secinfo");
SOAPElement userInfo = factory.createElement("UserInfo", "t", "http://schemas.xmlsoap.org/ws/2002/04/secext");
userInfo.setValue(userString);//"USER=THISUSER;CORR=THISCORR;TIMESTAMP="+timeStamp);
//format the document from inner most to outter most
signature.addChildElement(signedInfo);//1
signature.addChildElement(signatureValue);//2
keyInfo.addChildElement(keyName);//1
signature.addChildElement(keyInfo); //3
security.addChildElement(signature);
userNameToken.addChildElement(userInfo);
security.addChildElement(userNameToken);
soapHeader.addChildElement(security);
soapMsg.saveChanges();
System.out.println("Trying to print message.");
ByteArrayOutputStream out = new ByteArrayOutputStream();
soapMsg.writeTo(out);
String strMsg = new String(out.toByteArray());
System.out.println(strMsg);
System.out.println("End of handleMessage.");
} else {
//indound message not outbound
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
非常感谢任何帮助。