SOAP XML WS-Security签名验证 [英] SOAP XML WS-Security signature verification
问题描述
我能够使用WS-Security签名的证书对SOAP XML进行签名。但我无法验证其签名。在验证签名会导致异常时,将需要一些帮助来解决此问题
< s:Envelope xmlns:s =" http://schemas.xmlsoap.org/soap/envelope/"
< s:Header>
< ws:Security xmlns:ws =" http://schemas.xmlsoap.org/..." s:actor = test
< dsig:Signature xmlns:dsig = http://www.w3.org/2000/09 / ... id = Sample
...
< / dsig:Signature>
< / ws:Security>
< / s:Header>
< s:Body>
...
< / s:Body>
< / s:信封>
当我尝试验证SOAP XML时,出现以下异常:
org.apache.xml.security.signature.MissingResourceFailureException:URI #Body的引用没有XMLSignatureInput
public static boolean isSOAPXmlWSSEDigitalSignatureValid(StringsignedXmlFilePath,PublicKey publicKey)抛出异常{
String xmlContent = getFileString(signedXmlFilePath);
DocumentsignedDoc = getDocument(xmlContent.trim(),true);
signedDoc.createElementNS(DSIG_NS, ds); // qualifiedName = ds;
signatureDoc.createElementNS(WSU_NS, wsu);
signedDoc.createElementNS(WSSE_NS, wsse);
//加载签名
NodeList signatureNodes = signedDoc.getElementsByTagNameNS(javax.xml.crypto.dsig.XMLSignature.XMLNS, Signature);
if(signatureNodes.getLength()== 0){
抛出新的异常(未找到XML数字签名,文档被丢弃);
}
Element sigElement =(Element)signatureNodes.item(0);
if(sigElement == null)
抛出new Exception( Signature元素为null!);
org.apache.xml.security.Init.init();
org.apache.xml.security.signature.XMLSignature签名=新的XMLSignature(sigElement,);
return signature.checkSignatureValue(publicKey);
}
通过使用以下功能,我可以对XML进行签名
公共静态SOAPMessage WS_Security_signature(String inputFile,boolean isDataXML)引发异常{
SOAPMessage soapMsg;
文件docBody;
if(isDataXML){
System.out.println(示例数据xml-创建SOAP消息);
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
soapMsg = soapMessage;
字符串xmlContent = getFileString(inputFile);
docBody = getDocument(xmlContent.trim(),true);
System.out.println(数据文档: + docBody.getDocumentElement());
} else {
System.out.println(带有信封的SOAP XML);
文档doc = getDocument(inputFile,false); // SOAP MSG删除注释元素
String docStr = toStringDocument(doc); // https://stackoverflow.com/a/2567443/5081877
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(docStr.getBytes());
MimeHeaders mimeHeaders =新的MimeHeaders();
// SOAPMessage消息= MessageFactory.newInstance()。createMessage(null,fileInputStream);
SOAPMessage消息= MessageFactory.newInstance( SOAP 1.2协议).createMessage(mimeHeaders,byteArrayInputStream);
soapMsg =消息;
docBody = soapMsg.getSOAPBody()。extractContentAsDocument();
System.out.println( SOAP DATA Document: + docBody.getDocumentElement());
}
//一个新的SOAPMessage对象包含:•SOAPPart对象•SOAPEnvelope对象•SOAPBody对象•SOAPHeader对象
SOAPPart soapPart = soapMsg.getSOAPPart();
SOAPEnvelope soapEnv = soapPart.getEnvelope();
SOAPHeader soapHeader = soapEnv.getHeader(); // soapMessage.getSOAPHeader();
SOAPBody soapBody = soapEnv.getBody(); // soapMessage.getSOAPBody()
soapBody.addDocument(docBody);
soapBody.addAttribute(soapEnv.createName( Id, wsu,WSU_NS), Body);
if(soapHeader == null){
soapHeader = soapEnv.addHeader();
System.out.println(提供的SOAP XML不包含任何Header部分。因此创建它。);
}
//< wsse:Security>添加到标题部分
的元素SOAPElement securityElement = soapHeader.addChildElement( Security, wsse,WSSE_NS);
securityElement.addNamespaceDeclaration( wsu,WSU_NS);
字符串certEncodedID = X509Token,timeStampID = TS,signedBodyID = Body;
//(ii)添加二进制安全令牌。
//< wsse:BinarySecurityToken EncodingType = ...#Base64Binary; ValueType = ...#X509v3 wsu:Id = X509Token> ROS数字证书的base64编码值。
SOAPElement binarySecurityToken = securityElement.addChildElement( BinarySecurityToken, wsse);
binarySecurityToken.setAttribute( ValueType,binarySecurityToken_Value);
binarySecurityToken.setAttribute( EncodingType,binarySecurityToken_Encoding);
binarySecurityToken.setAttribute( wsu:Id,certEncodedID);
byte [] certByte = loadPublicKeyX509.getEncoded();
字符串encodeToString = Base64.getEncoder()。encodeToString(certByte);
binarySecurityToken.addTextNode(encodeToString);
//(iii)添加TimeStamp元素-< wsu:Timestamp wsu:Id =" TS>
SOAPElement timestamp = securityElement.addChildElement( Timestamp, wsu);
timestamp.addAttribute(soapEnv.createName( Id, wsu,WSU_NS),timeStampID);
字符串DATE_TIME_PATTERN = yyyy-MM-dd’T’HH:mm:ss.SSSX;
DateTimeFormatter timeStampFormatter = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
timestamp.addChildElement( Created, wsu)。setValue(timeStampFormatter.format(ZonedDateTime.now()。toInstant()。atZone(ZoneId.of( UTC))))));
timestamp.addChildElement( Expires, wsu)。setValue(timeStampFormatter.format(ZonedDateTime.now()。plusSeconds(30).toInstant()。atZone(ZoneId.of( UTC); ))));
//(iv)添加签名元素
// //< wsse:Security> < ds:Signature> < ds:KeyInfo> < wsse:SecurityTokenReference>
SOAPElement securityTokenReference = securityElement.addChildElement( SecurityTokenReference, wsse);
SOAPElement参考= securityTokenReference.addChildElement( Reference, wsse);
reference.setAttribute( URI,# + certEncodedID); //< wsse:BinarySecurityToken wsu:Id = X509Token;
//< ds:SignedInfo>
字符串providerName = System.getProperty( jsr105Provider, org.jcp.xml.dsig.internal.dom.XMLDSigRI);
XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance( DOM,(提供者)Class.forName(providerName).newInstance());
//摘要方法-< ds:SignatureMethod Algorithm = http://www.w3.org/2000/09/xmldsig#rsa-sha1 />
javax.xml.crypto.dsig.DigestMethod摘要方法= xmlSignatureFactory.newDigestMethod(digestMethodAlog_SHA1,null);
ArrayList< Transform> transformList = new ArrayList< Transform>();
//转换-< ds:Reference URI ='#Body'>
转换envTransform = xmlSignatureFactory.newTransform(transformAlog,(TransformParameterSpec)null);
transformList.add(envTransform);
//参考文献< ds:参考文献URI =#Body>
ArrayList< Reference> refList = new ArrayList< Reference>();
参考refTS = xmlSignatureFactory.newReference(# + timeStampID,digestMethod,transformList,null,null);
参考refBody = xmlSignatureFactory.newReference(# + signedBodyID,digestMethod,transformList,null,null);
refList.add(refBody);
refList.add(refTS);
javax.xml.crypto.dsig.CanonicalizationMethod cm = xmlSignatureFactory.newCanonicalizationMethod(canonicalizerAlog,(C14NMethodParameterSpec)null);
javax.xml.crypto.dsig.SignatureMethod sm = xmlSignatureFactory.newSignatureMethod(signatureMethodAlog_SHA1,null);
SignedInfo signatureInfo = xmlSignatureFactory.newSignedInfo(cm,sm,refList);
DOMSignContext signContext =新的DOMSignContext(privateKey,securityElement);
signContext.setDefaultNamespacePrefix( ds);
signContext.putNamespacePrefix(DSIG_NS, ds);
signContext.putNamespacePrefix(WSU_NS, wsu);
signContext.setIdAttributeNS(soapBody,WSU_NS, Id);
signContext.setIdAttributeNS(timestamp,WSU_NS, Id);
KeyInfoFactory keyFactory = KeyInfoFactory.getInstance();
DOMStructure domKeyInfo =新的DOMStructure(securityTokenReference);
javax.xml.crypto.dsig.keyinfo.KeyInfo keyInfo = keyFactory.newKeyInfo(java.util.Collections.singletonList(domKeyInfo));
javax.xml.crypto.dsig.XMLSignature签名= xmlSignatureFactory.newXMLSignature(signedInfo,keyInfo);
signContext.setBaseURI();
signature.sign(signContext);
返还肥皂
}
使用证书和私钥 Baeldung.cer,Baeldung.p12 (密码=密码)
//依赖关系:groupId:xml-security,artifactId:xmlsec,版本:1.3.0
//依赖关系:groupId:xalan ,artifactId:xalan,版本:2.7.1
公共类SOAP_Security_Signature {
静态最终字符串
WSSE_NS = http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-wssecurity-secext-1.0.xsd,
WSU_NS = http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-实用程序-1.0.xsd,
DSIG_NS = http://www.w3.org/2000/09/xmldsig#,// javax.xml.crypto.dsig.XMLSignature.XMLNS,常量。 SignatureSpecNS
binarySecurityToken_Encoding = http://docs.oasis-open.org/wss/2004/01/oasis-200 401-wss-soap-message-security-1.0#Base64Binary,
binarySecurityToken_Value = http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token -profile-1.0#X509v3,
signatureMethodAlog_SHA1 = DSIG_NS + rsa-sha1,// XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1
digestMethodAlog_SHA1 = Constants.ALGO_ID_DIGEST_SHA1,// DSIG_NS ,// Constants.ALGO_ID_DIGEST_SHA1
transformAlog = Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS,//\"http://www.w3.org/2001/10/xml-exc-c14n#;
canonicalizerAlog = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; //"http://www.w3.org/2001/10/xml-exc-c14n#" ;; CanonicalizationMethod.EXCLUSIVE
静态{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
}
公共静态X509Certificate loadPublicKeyX509(InputStream cerFileStream)抛出CertificateException,NoSuchProviderException {
CertificateFactory certificateFactory = CertificateFactory.getInstance( X.509, BC);
X509Certificate x509Certificate =(X509Certificate)certificateFactory.generateCertificate(cerFileStream);
return x509Certificate;
}
公共静态私有密钥loadPrivateKeyforSigning(InputStream cerFileStream,字符串密码)抛出UnrecoverableKeyException,KeyStoreException,NoSuchAlgorithmException,CertificateException,IOException,NoSuchProviderException {
KeyStore keyStore = KeyStore.getInstance( PKCS12); //, BC);
keyStore.load(cerFileStream,password.toCharArray());
Enumeration< String> keyStoreAliasEnum = keyStore.aliases();
PrivateKey privateKey = null;
字符串别名= null;
if(keyStoreAliasEnum.hasMoreElements()){
alias = keyStoreAliasEnum.nextElement();
if(password!= null){
privateKey =(PrivateKey)keyStore.getKey(alias,password.toCharArray());
}
}
返回privateKey;
}
静态X509证书loadPublicKeyX509;
静态PrivateKey privateKey;
静态字符串路径= C:/ Yash / SOAP /,privateKeyFilePath =路径+ Baeldung.p12,publicKeyFilePath =路径+ Baeldung.cer,
inputFile = path + Soap1.xml,outputFile =路径+ output.xml;
public static void main(String [] args)引发异常{
InputStream pkcs_FileStream = new FileInputStream(privateKeyFilePath);
privateKey = loadPrivateKeyforSigning(pkcs_FileStream, password));
System.out.println( privateKey: + privateKey);
InputStream cerFileStream = new FileInputStream(publicKeyFilePath);
loadPublicKeyX509 = loadPublicKeyX509(cerFileStream);
PublicKey publicKey = loadPublicKeyX509.getPublicKey();
System.out.println( loadPublicKey:" + publicKey);
System.setProperty( javax.xml.soap.MessageFactory, com.sun.xml.internal.messaging.saaj.soap.ver1_2.SOAPMessageFactory1_2Impl);
System.setProperty( javax.xml.bind.JAXBContext, com.sun.xml.internal.bind.v2.ContextFactory);
SOAPMessage soapMsg = WS_Security_signature(inputFile,false);
outputSOAPMessageToFile(soapMsg);
System.out.println( Signature Succesfull.Verify the Signature);
boolean soapXmlWSSEDigitalSignatureValid = isSOAPXmlWSSEDigitalSignatureValid(outputFile,publicKey);
System.out.println( isSOAPXmlDigitalSignatureValid: + soapXmlWSSEDigitalSignatureValid);
}
公共静态无效outputSOAPMessageToFile(SOAPMessage soapMessage)抛出SOAPException,IOException {
File outputFileNew = new File(outputFile);
java.io.FileOutputStream fos = new java.io.FileOutputStream(outputFileNew);
soapMessage.writeTo(fos);
fos.close();
}
公共静态字符串toStringDocument(Document doc)引发TransformerException {
StringWriter sw = new StringWriter();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer变压器= tf.newTransformer();
Transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, no);
Transformer.setOutputProperty(OutputKeys.METHOD, xml);
Transformer.setOutputProperty(OutputKeys.INDENT, yes);
Transformer.setOutputProperty(OutputKeys.ENCODING, UTF-8);
Transformer.transform(new DOMSource(doc),new StreamResult(sw));
return sw.toString();
}
公共静态字符串getFileString(String xmlFilePath)抛出FileNotFoundException {
File file = new File(xmlFilePath);
// FileInputStream parseXMLStream = new FileInputStream(file.getAbsolutePath());
扫描仪扫描仪=新的扫描仪(文件, UTF-8);
字符串xmlContent = Scanner.useDelimiter( \\A)。next();
Scanner.close(); //将此调用放入最后一个块
System.out.println( Str: + xmlContent);
返回xmlContent;
}
公共静态文档getDocument(String xmlData,boolean isXMLData)引发异常{
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true);
dbFactory.setIgnoringComments(true);
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
文件文件;
if(isXMLData){
InputSource ips = new org.xml.sax.InputSource(new StringReader(xmlData));
doc = dBuilder.parse(ips);
} else {
doc = dBuilder.parse(new File(xmlData));
}
退货单据;
}
private void callTheWebServiceFromFile()引发IOException,SOAPException {
//加载soap请求文件
File soapFile = new File(outputFile);
FileInputStream fis =新的FileInputStream(soapFile);
javax.xml.transform.stream.StreamSource ss = new javax.xml.transform.stream.StreamSource(fis);
//创建SOAP消息对象
SOAPMessage msg = MessageFactory.newInstance()。createMessage();
SOAPPart soapPart = msg.getSOAPPart();
//使用流源
soapPart.setContent(ss)设置soapPart内容;
//创建一个Web服务连接
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
//调用webService。
字符串soapEndpointUrl = https://softwaretest.ros.ie/paye-employers/v1/soap;
SOAPMessage resp = soapConnection.call(msg,soapEndpointUrl);
//读取结果
resp.writeTo(System.out);
fis.close();
soapConnection.close();
}
}
输入要签名的SOAP XML:
< pre class = lang-xml prettyprint-override>
<?xml version = 1.0 encoding = UTF-8 standalone =否?
< env:Envelope xmlns:env =" http://www.w3.org/2003/05/soap-envelope>
< env:Body>
<产品版本= 11.1.2.4.0> <!-数据XML->
< name> API网关< / name>
< company> Oracle< / company>
< description> SOA安全性和管理< / description>
< / product>
< / env:Body>
< / env:Envelope>
WS-Security签名XML:
<?xml version = 1.0 encoding = UTF-8?
< env:Envelope
xmlns:env =" http://www.w3.org/2003/05/soap-envelope>
< 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>
< wsse:BinarySecurityToken EncodingType = http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary ValueType = http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3 WSU:编号= QUOT; X509Token"> MIIDPjCCAiagAwIBAgIJAPvd1gx14C3CMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNVBAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNhYmxhbmNhMREwDwYDVQQDEwhCYWVsZHVuZzAeFw0xNzEwMTIxMDQzMTRaFw0yNzEwMTMxMDQzMTRaMEcxCzAJBgNVBAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNhYmxhbmNhMREwDwYDVQQDEwhCYWVsZHVuZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMyi5GmOeN4QaH / CP5gSOyHX8znb5TDHWV8wc + ZT7kNU8zt5tGMhjozK6hax155 / 6tOsBDR0rSYBhL + DM / + uCVS7qOlRHhf6cNGtzGF1gnNJB2WjI8oMAYm24xpLj1WphKUwKrn3nTMPnQup5OoNAMYl99flANrRYVjjxrLQvDZDUio6IujrCZ2TtXGM0g / GP ++ 28KT7g1KlUui3xtB0u33wx7UN8Fix3JmjOaPHGwxGpwP3VGSjfs8cuhqVwRQaZpCOoHU / P8wpXKw80sSdhz + SRueMPtVYqK0CiLL5 / O0h0Y3le4IVwhgg3KG1iTGOWn60UMFn1EYmQ18k5Nsma6UCAwEAAaMtMCswCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBPAwCwYDVR0PBAQDAgUgMA0GCSqGSIb3DQEBBQUAA4IBAQC8DDBmJ3p4xytxBiE0s4p1715WT6Dm / QJHp0XC0hkSoyZKDh + XVmrzm + J3SiW1vpswb5hLgPo040YX9jnDmgOD + TpleTuKHxZRYj92UYWmdjkWLVtFMcvOh + gxBiAPpHIqZsqo8lfcyAuh8Jx834IXbknfCUtERDLG / rU9P / 3XJhrM2GC5qPQznrW4EYhUCGPyIJXm vATMVvXMWCtfogAL + n42vjYXQXZoAWomHhLHoNbSJUErnNdWDOh4WoJtXJCxA6U5LSBplqb3wB2hUTqw + 0admKltvmy + KA1PD7OxoGiY7V544zeGqJy1SV
< wsu:Timestamp wsu:Id = TS>
< wsu:Created> 2020-08-27T12:03:23.288Z< / wsu:Created>
< wsu:Expires> 2020-08-27T12:03:53.293Z< / wsu:Expires>
< / wsu:Timestamp>
< ds:签名
xmlns:ds =" http://www.w3.org/2000/09/xmldsig#">
< ds:SignedInfo>
< ds:CanonicalizationMethod Algorithm = http://www.w3.org/2001/10/xml-exc-c14n# />
< ds:SignatureMethod Algorithm =" http://www.w3.org/2000/09/xmldsig#rsa-sha1>
< ds:参考URI =#Body>
< ds:Transforms>
< ds:Transform Algorithm = http://www.w3.org/2001/10/xml-exc-c14n# />
< / ds:Transforms>
< ds:DigestMethodAlgorithm = http://www.w3.org/2000/09/xmldsig#sha1 />
< ds:DigestValue> RU8XbQ1 / kx / CPZpgxG9fa / lia8Q =< / ds:DigestValue>
< / ds:Reference>
< ds:参考URI =#TS>
< ds:Transforms>
< ds:Transform Algorithm = http://www.w3.org/2001/10/xml-exc-c14n# />
< / ds:Transforms>
< ds:DigestMethodAlgorithm = http://www.w3.org/2000/09/xmldsig#sha1 />
< ds:DigestValue> YZTSgGN / tvrcpeFZ00aWCpVrXZU =< / ds:DigestValue>
< / ds:Reference>
< / ds:SignedInfo>
将DS:SignatureValue所> hgGYDvkc3YPG1ptb6FMnQJV0t1GExjHIOGsXjAwG6uIYLDvkt10ve + AOynBAiSP0CR1NDI6mlXd +
5v5oa2XLEcbuO62v8yj0o1Kr + gkiaf1zo / qZkpwyT5iBkmabNcEzRE8iDCKwTOfFkG4PVRkCOE0D
Q4I84AeYnLAHaoF9IGpbjk0MdXKFIsSTmAmR92BHnjsOyUi1CD6N / 7GDscNLfYoEtMEwovFbupUP
qbJNaq + M / bi5dnTEVqG / TIGftc / me8NVXQiohRq6U8sSAMbLdF5P + iGivcqlLD5xthXfBPHpwruK
euXNan7Jxc9cc5QFx3Rcirvqg / iJ0sPAHRuPGQ ==< / ds:SignatureValue>
< ds:KeyInfo>
< wsse:SecurityTokenReference>
< wsse:Reference URI =#X509Token />
< / wsse:SecurityTokenReference>
< / ds:KeyInfo>
< / ds:Signature>
< / wsse:Security>
< / env:Header>
< env:Body
xmlns:wsu = http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd ; wsu:Id = Body>
<产品版本= 11.1.2.4.0>
< name> API网关< / name>
< company> Oracle< / company>
< description> SOA安全性和管理< / description>
< / product>
< / env:Body>
< / env:Envelope>
用于SOAP XML数字签名 我能够签名并验证
。
SOAP XML信封签名:
< s:Envelope xmlns:s =" http://schemas.xmlsoap.org/soap/envelope />
< s:Header>
< dsig:Signature xmlns:dsig = http://www.w3.org/2000/09 / ... id = Sample
...
< / dsig:Signature>
< / s:Header>
< s:Body>
...
< / s:Body>
< / s:信封>
在您的 isSOAPXmlWSSEDigitalSignatureValid
方法,您需要为每个 Reference
d元素显式设置 Id
属性作为元素id属性,则默认情况下不采用它们: https://issues.apache.org/jira/浏览/ SANTUARIO-312
public static boolean isSOAPXmlWSSEDigitalSignatureValid(StringsignedXmlFilePath,PublicKey publicKey)引发异常{
字符串xmlContent = getFileString(signedXmlFilePath);
DocumentsignedDoc = getDocument(xmlContent,true);
signedDoc.createElementNS(DSIG_NS, ds); // qualifiedName = ds;
signedDoc.createElementNS(WSU_NS, wsu);
signedDoc.createElementNS(WSSE_NS, wsse);
//为SOAP正文元素
注册XML ID NodeList soapBodyElements = signedDoc.getElementsByTagNameNS( http://www.w3.org/2003/05/soap-envelope, ; Body);
if(soapBodyElements.getLength()== 0){
抛出new Exception(找不到元素SOAP主体);
}
元素soapBodyElement =(Element)soapBodyElements.item(0);
soapBodyElement.setIdAttributeNS( http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd, Id,true) ;
//为时间戳记元素
注册XML ID NodeList时间戳记= signedDoc.getElementsByTagNameNS( http://docs.oasis-open.org/wss/2004/01/oasis-200401 -wss-wssecurity-utility-1.0.xsd, Timestamp);
if(timestamps.getLength()== 0){
throw new Exception( Element Timestamp not found);
}
Element timestampElement =(Element)timestamps.item(0);
timestampElement.setIdAttributeNS( http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd, Id,true) ;
//加载签名
NodeList signatureNodes = signedDoc.getElementsByTagNameNS(javax.xml.crypto.dsig.XMLSignature.XMLNS, Signature);
if(signatureNodes.getLength()== 0){
抛出新的异常(未找到XML数字签名,文档被丢弃);
}
Element sigElement =(Element)signatureNodes.item(0);
if(sigElement == null)
抛出new Exception( Signature元素为null!);
Init.init();
XMLSignature签名=新的XMLSignature(sigElement,);
return signature.checkSignatureValue(publicKey);
}
I am able to sign the SOAP XML using a certificate for the WS-Security signature. But i am unable to verify its signature. On verifying the signature it leads to Exception, Some help will be appreciated to resolve the issue
SOAP Enveloped WS-Security signature:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<ws:Security xmlns:ws="http://schemas.xmlsoap.org/..." s:actor="test">
<dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/..." id="Sample">
...
</dsig:Signature>
</ws:Security>
</s:Header>
<s:Body>
...
</s:Body>
</s:Envelope>
When i try to verify the SOAP XML i am getting the following Exception:
org.apache.xml.security.signature.MissingResourceFailureException: The Reference for URI #Body has no XMLSignatureInput
public static boolean isSOAPXmlWSSEDigitalSignatureValid(String signedXmlFilePath, PublicKey publicKey) throws Exception {
String xmlContent = getFileString(signedXmlFilePath);
Document signedDoc = getDocument(xmlContent.trim(), true);
signedDoc.createElementNS(DSIG_NS, "ds"); // qualifiedName = "ds";
signedDoc.createElementNS(WSU_NS, "wsu");
signedDoc.createElementNS(WSSE_NS, "wsse");
// load signature
NodeList signatureNodes = signedDoc.getElementsByTagNameNS(javax.xml.crypto.dsig.XMLSignature.XMLNS, "Signature");
if (signatureNodes.getLength() == 0) {
throw new Exception("No XML Digital Signature Found, document is discarded");
}
Element sigElement = (Element) signatureNodes.item(0);
if (sigElement == null)
throw new Exception("Signature element is null!");
org.apache.xml.security.Init.init();
org.apache.xml.security.signature.XMLSignature signature = new XMLSignature(sigElement, "");
return signature.checkSignatureValue(publicKey);
}
By Using the following function i am able to sign the XML
public static SOAPMessage WS_Security_signature(String inputFile, boolean isDataXML) throws Exception {
SOAPMessage soapMsg;
Document docBody;
if (isDataXML) {
System.out.println("Sample DATA xml - Create SOAP Message");
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
soapMsg = soapMessage;
String xmlContent = getFileString(inputFile);
docBody = getDocument(xmlContent.trim(), true);
System.out.println("Data Document: "+docBody.getDocumentElement());
} else {
System.out.println("SOAP XML with Envelope");
Document doc = getDocument(inputFile, false); // SOAP MSG removing comment elements
String docStr = toStringDocument(doc); // https://stackoverflow.com/a/2567443/5081877
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(docStr.getBytes());
MimeHeaders mimeHeaders = new MimeHeaders();
// SOAPMessage message = MessageFactory.newInstance().createMessage(null, fileInputStream);
SOAPMessage message = MessageFactory.newInstance("SOAP 1.2 Protocol").createMessage(mimeHeaders, byteArrayInputStream);
soapMsg = message;
docBody = soapMsg.getSOAPBody().extractContentAsDocument();
System.out.println("SOAP DATA Document: "+docBody.getDocumentElement());
}
// A new SOAPMessage object contains: •SOAPPart object •SOAPEnvelope object •SOAPBody object •SOAPHeader object
SOAPPart soapPart = soapMsg.getSOAPPart();
SOAPEnvelope soapEnv = soapPart.getEnvelope();
SOAPHeader soapHeader = soapEnv.getHeader(); // soapMessage.getSOAPHeader();
SOAPBody soapBody = soapEnv.getBody(); // soapMessage.getSOAPBody()
soapBody.addDocument(docBody);
soapBody.addAttribute(soapEnv.createName("Id", "wsu", WSU_NS), "Body");
if (soapHeader == null) {
soapHeader = soapEnv.addHeader();
System.out.println("Provided SOAP XML does not contains any Header part. So creating it.");
}
// <wsse:Security> element adding to Header Part
SOAPElement securityElement = soapHeader.addChildElement("Security", "wsse", WSSE_NS);
securityElement.addNamespaceDeclaration("wsu", WSU_NS);
String certEncodedID = "X509Token", timeStampID = "TS", signedBodyID = "Body";
// (ii) Add Binary Security Token.
// <wsse:BinarySecurityToken EncodingType="...#Base64Binary" ValueType="...#X509v3" wsu:Id="X509Token">The base64 encoded value of the ROS digital certificate.</wsse:BinarySecurityToken>
SOAPElement binarySecurityToken = securityElement.addChildElement("BinarySecurityToken", "wsse");
binarySecurityToken.setAttribute("ValueType", binarySecurityToken_Value);
binarySecurityToken.setAttribute("EncodingType", binarySecurityToken_Encoding);
binarySecurityToken.setAttribute("wsu:Id", certEncodedID);
byte[] certByte = loadPublicKeyX509.getEncoded();
String encodeToString = Base64.getEncoder().encodeToString(certByte);
binarySecurityToken.addTextNode(encodeToString);
//(iii) Add TimeStamp element - <wsu:Timestamp wsu:Id="TS">
SOAPElement timestamp = securityElement.addChildElement("Timestamp", "wsu");
timestamp.addAttribute(soapEnv.createName("Id", "wsu", WSU_NS), timeStampID);
String DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSX";
DateTimeFormatter timeStampFormatter = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
timestamp.addChildElement("Created", "wsu").setValue(timeStampFormatter.format(ZonedDateTime.now().toInstant().atZone(ZoneId.of("UTC"))));
timestamp.addChildElement("Expires", "wsu").setValue(timeStampFormatter.format(ZonedDateTime.now().plusSeconds(30).toInstant().atZone(ZoneId.of("UTC"))));
// (iv) Add signature element
// <wsse:Security> <ds:Signature> <ds:KeyInfo> <wsse:SecurityTokenReference>
SOAPElement securityTokenReference = securityElement.addChildElement("SecurityTokenReference", "wsse");
SOAPElement reference = securityTokenReference.addChildElement("Reference", "wsse");
reference.setAttribute("URI", "#"+certEncodedID); // <wsse:BinarySecurityToken wsu:Id="X509Token"
// <ds:SignedInfo>
String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).newInstance());
//Digest method - <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
javax.xml.crypto.dsig.DigestMethod digestMethod = xmlSignatureFactory.newDigestMethod(digestMethodAlog_SHA1, null);
ArrayList<Transform> transformList = new ArrayList<Transform>();
//Transform - <ds:Reference URI="#Body">
Transform envTransform = xmlSignatureFactory.newTransform(transformAlog, (TransformParameterSpec) null);
transformList.add(envTransform);
//References <ds:Reference URI="#Body">
ArrayList<Reference> refList = new ArrayList<Reference>();
Reference refTS = xmlSignatureFactory.newReference("#"+timeStampID, digestMethod, transformList, null, null);
Reference refBody = xmlSignatureFactory.newReference("#"+signedBodyID, digestMethod, transformList, null, null);
refList.add(refBody);
refList.add(refTS);
javax.xml.crypto.dsig.CanonicalizationMethod cm = xmlSignatureFactory.newCanonicalizationMethod(canonicalizerAlog, (C14NMethodParameterSpec) null);
javax.xml.crypto.dsig.SignatureMethod sm = xmlSignatureFactory.newSignatureMethod(signatureMethodAlog_SHA1, null);
SignedInfo signedInfo = xmlSignatureFactory.newSignedInfo(cm, sm, refList);
DOMSignContext signContext = new DOMSignContext(privateKey, securityElement);
signContext.setDefaultNamespacePrefix("ds");
signContext.putNamespacePrefix(DSIG_NS, "ds");
signContext.putNamespacePrefix(WSU_NS, "wsu");
signContext.setIdAttributeNS(soapBody, WSU_NS, "Id");
signContext.setIdAttributeNS(timestamp, WSU_NS, "Id");
KeyInfoFactory keyFactory = KeyInfoFactory.getInstance();
DOMStructure domKeyInfo = new DOMStructure(securityTokenReference);
javax.xml.crypto.dsig.keyinfo.KeyInfo keyInfo = keyFactory.newKeyInfo(java.util.Collections.singletonList(domKeyInfo));
javax.xml.crypto.dsig.XMLSignature signature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo);
signContext.setBaseURI("");
signature.sign(signContext);
return soapMsg;
}
Full Example which uses the Certificate And Private Key Baeldung.cer, Baeldung.p12 (password = "password")
// dependency: groupId:xml-security, artifactId:xmlsec, version:1.3.0
// dependency: groupId:xalan, artifactId:xalan, version:2.7.1
public class SOAP_Security_Signature {
static final String
WSSE_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
WSU_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd",
DSIG_NS = "http://www.w3.org/2000/09/xmldsig#", // javax.xml.crypto.dsig.XMLSignature.XMLNS, Constants.SignatureSpecNS
binarySecurityToken_Encoding = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary",
binarySecurityToken_Value = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3",
signatureMethodAlog_SHA1 = DSIG_NS + "rsa-sha1", // XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1
digestMethodAlog_SHA1 = Constants.ALGO_ID_DIGEST_SHA1, // DSIG_NS + "sha1", // Constants.ALGO_ID_DIGEST_SHA1
transformAlog = Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS, //"http://www.w3.org/2001/10/xml-exc-c14n#";
canonicalizerAlog = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; //"http://www.w3.org/2001/10/xml-exc-c14n#"; CanonicalizationMethod.EXCLUSIVE
static {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
}
public static X509Certificate loadPublicKeyX509(InputStream cerFileStream) throws CertificateException, NoSuchProviderException {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", "BC");
X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(cerFileStream);
return x509Certificate;
}
public static PrivateKey loadPrivateKeyforSigning(InputStream cerFileStream, String password) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, NoSuchProviderException {
KeyStore keyStore = KeyStore.getInstance("PKCS12"); //, "BC");
keyStore.load(cerFileStream, password.toCharArray());
Enumeration<String> keyStoreAliasEnum = keyStore.aliases();
PrivateKey privateKey = null;
String alias = null;
if ( keyStoreAliasEnum.hasMoreElements() ) {
alias = keyStoreAliasEnum.nextElement();
if (password != null) {
privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
}
}
return privateKey;
}
static X509Certificate loadPublicKeyX509;
static PrivateKey privateKey;
static String path = "C:/Yash/SOAP/", privateKeyFilePath = path+"Baeldung.p12", publicKeyFilePath = path+"Baeldung.cer",
inputFile= path+"Soap1.xml", outputFile = path+"output.xml";
public static void main(String[] args) throws Exception {
InputStream pkcs_FileStream = new FileInputStream(privateKeyFilePath);
privateKey = loadPrivateKeyforSigning(pkcs_FileStream, "password");
System.out.println("privateKey : "+privateKey);
InputStream cerFileStream = new FileInputStream(publicKeyFilePath);
loadPublicKeyX509 = loadPublicKeyX509(cerFileStream);
PublicKey publicKey = loadPublicKeyX509.getPublicKey();
System.out.println("loadPublicKey : "+ publicKey);
System.setProperty("javax.xml.soap.MessageFactory", "com.sun.xml.internal.messaging.saaj.soap.ver1_2.SOAPMessageFactory1_2Impl");
System.setProperty("javax.xml.bind.JAXBContext", "com.sun.xml.internal.bind.v2.ContextFactory");
SOAPMessage soapMsg = WS_Security_signature(inputFile, false);
outputSOAPMessageToFile(soapMsg);
System.out.println("Signature Succesfull. Verify the Signature");
boolean soapXmlWSSEDigitalSignatureValid = isSOAPXmlWSSEDigitalSignatureValid(outputFile, publicKey);
System.out.println("isSOAPXmlDigitalSignatureValid :"+soapXmlWSSEDigitalSignatureValid);
}
public static void outputSOAPMessageToFile(SOAPMessage soapMessage) throws SOAPException, IOException {
File outputFileNew = new File(outputFile);
java.io.FileOutputStream fos = new java.io.FileOutputStream(outputFileNew);
soapMessage.writeTo(fos);
fos.close();
}
public static String toStringDocument(Document doc) throws TransformerException {
StringWriter sw = new StringWriter();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.transform(new DOMSource(doc), new StreamResult(sw));
return sw.toString();
}
public static String getFileString(String xmlFilePath) throws FileNotFoundException {
File file = new File(xmlFilePath);
//FileInputStream parseXMLStream = new FileInputStream(file.getAbsolutePath());
Scanner scanner = new Scanner( file, "UTF-8" );
String xmlContent = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block
System.out.println("Str:"+xmlContent);
return xmlContent;
}
public static Document getDocument(String xmlData, boolean isXMLData) throws Exception {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true);
dbFactory.setIgnoringComments(true);
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc;
if (isXMLData) {
InputSource ips = new org.xml.sax.InputSource(new StringReader(xmlData));
doc = dBuilder.parse(ips);
} else {
doc = dBuilder.parse( new File(xmlData) );
}
return doc;
}
private void callTheWebServiceFromFile() throws IOException, SOAPException {
//load the soap request file
File soapFile = new File(outputFile);
FileInputStream fis = new FileInputStream(soapFile);
javax.xml.transform.stream.StreamSource ss = new javax.xml.transform.stream.StreamSource(fis);
// Create a SOAP Message Object
SOAPMessage msg = MessageFactory.newInstance().createMessage();
SOAPPart soapPart = msg.getSOAPPart();
// Set the soapPart Content with the stream source
soapPart.setContent(ss);
// Create a webService connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Invoke the webService.
String soapEndpointUrl = "https://softwaretest.ros.ie/paye-employers/v1/soap";
SOAPMessage resp = soapConnection.call(msg, soapEndpointUrl);
// Reading result
resp.writeTo(System.out);
fis.close();
soapConnection.close();
}
}
Input SOAP XML to Sign:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Body>
<product version="11.1.2.4.0"> <!-- Data XML -->
<name>API Gateway</name>
<company>Oracle</company>
<description>SOA Security and Management</description>
</product>
</env:Body>
</env:Envelope>
WS-Security Signed XML:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope
xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<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">
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509Token">MIIDPjCCAiagAwIBAgIJAPvd1gx14C3CMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNVBAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNhYmxhbmNhMREwDwYDVQQDEwhCYWVsZHVuZzAeFw0xNzEwMTIxMDQzMTRaFw0yNzEwMTMxMDQzMTRaMEcxCzAJBgNVBAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNhYmxhbmNhMREwDwYDVQQDEwhCYWVsZHVuZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMyi5GmOeN4QaH/CP5gSOyHX8znb5TDHWV8wc+ZT7kNU8zt5tGMhjozK6hax155/6tOsBDR0rSYBhL+Dm/+uCVS7qOlRHhf6cNGtzGF1gnNJB2WjI8oMAYm24xpLj1WphKUwKrn3nTMPnQup5OoNAMYl99flANrRYVjjxrLQvDZDUio6IujrCZ2TtXGM0g/gP++28KT7g1KlUui3xtB0u33wx7UN8Fix3JmjOaPHGwxGpwP3VGSjfs8cuhqVwRQaZpCOoHU/P8wpXKw80sSdhz+SRueMPtVYqK0CiLL5/O0h0Y3le4IVwhgg3KG1iTGOWn60UMFn1EYmQ18k5Nsma6UCAwEAAaMtMCswCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBPAwCwYDVR0PBAQDAgUgMA0GCSqGSIb3DQEBBQUAA4IBAQC8DDBmJ3p4xytxBiE0s4p1715WT6Dm/QJHp0XC0hkSoyZKDh+XVmrzm+J3SiW1vpswb5hLgPo040YX9jnDmgOD+TpleTuKHxZRYj92UYWmdjkWLVtFMcvOh+gxBiAPpHIqZsqo8lfcyAuh8Jx834IXbknfCUtERDLG/rU9P/3XJhrM2GC5qPQznrW4EYhUCGPyIJXmvATMVvXMWCtfogAL+n42vjYXQXZoAWomHhLHoNbSJUErnNdWDOh4WoJtXJCxA6U5LSBplqb3wB2hUTqw+0admKltvmy+KA1PD7OxoGiY7V544zeGqJam1qxUia7y5BL6uOa/4ShSV8pcJDYz</wsse:BinarySecurityToken>
<wsu:Timestamp wsu:Id="TS">
<wsu:Created>2020-08-27T12:03:23.288Z</wsu:Created>
<wsu:Expires>2020-08-27T12:03:53.293Z</wsu:Expires>
</wsu:Timestamp>
<ds:Signature
xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#Body">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>RU8XbQ1/kx/CPZpgxG9fa/lia8Q=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#TS">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>YZTSgGN/tvrcpeFZ00aWCpVrXZU=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>hgGYDvkc3YPG1ptb6FMnQJV0t1GExjHIOGsXjAwG6uIYLDvkt10ve+AOynBAiSP0CR1NDI6mlXd+
5v5oa2XLEcbuO62v8yj0o1Kr+gkiaf1zo/qZkpwyT5iBkmabNcEzRE8iDCKwTOfFkG4PVRkCOE0D
Q4I84AeYnLAHaoF9IGpbjk0MdXKFIsSTmAmR92BHnjsOyUi1CD6N/7GDscNLfYoEtMEwovFbupUP
qbJNaq+M/bi5dnTEVqG/TIGftc/me8NVXQiohRq6U8sSAMbLdF5P+iGivcqlLD5xthXfBPHpwruK
euXNan7Jxc9cc5QFx3Rcirvqg/iJ0sPAHRuPGQ==</ds:SignatureValue>
<ds:KeyInfo>
<wsse:SecurityTokenReference>
<wsse:Reference URI="#X509Token"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</env:Header>
<env:Body
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Body">
<product version="11.1.2.4.0">
<name>API Gateway</name>
<company>Oracle</company>
<description>SOA Security and Management</description>
</product>
</env:Body>
</env:Envelope>
For SOAP XML digital signature i am able to sign and verify
.
SOAP XML Enveloped Signature:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/..." id="Sample">
...
</dsig:Signature>
</s:Header>
<s:Body>
...
</s:Body>
</s:Envelope>
In your isSOAPXmlWSSEDigitalSignatureValid
method you need to set explicitly the Id
attribute as the element id attribute for every Reference
d element, they are not assumed by default: https://issues.apache.org/jira/browse/SANTUARIO-312
public static boolean isSOAPXmlWSSEDigitalSignatureValid(String signedXmlFilePath, PublicKey publicKey) throws Exception {
String xmlContent = getFileString(signedXmlFilePath);
Document signedDoc = getDocument(xmlContent, true);
signedDoc.createElementNS(DSIG_NS, "ds"); // qualifiedName = "ds";
signedDoc.createElementNS(WSU_NS, "wsu");
signedDoc.createElementNS(WSSE_NS, "wsse");
// Register XML ID for SOAP Body element
NodeList soapBodyElements = signedDoc.getElementsByTagNameNS("http://www.w3.org/2003/05/soap-envelope", "Body");
if (soapBodyElements.getLength() == 0) {
throw new Exception("Element SOAP Body not found");
}
Element soapBodyElement = (Element) soapBodyElements.item(0);
soapBodyElement.setIdAttributeNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Id", true);
// Register XML ID for Timestamp element
NodeList timestamps = signedDoc.getElementsByTagNameNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Timestamp");
if (timestamps.getLength() == 0) {
throw new Exception("Element Timestamp not found");
}
Element timestampElement = (Element) timestamps.item(0);
timestampElement.setIdAttributeNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Id", true);
// load signature
NodeList signatureNodes = signedDoc.getElementsByTagNameNS(javax.xml.crypto.dsig.XMLSignature.XMLNS, "Signature");
if (signatureNodes.getLength() == 0) {
throw new Exception("No XML Digital Signature Found, document is discarded");
}
Element sigElement = (Element) signatureNodes.item(0);
if (sigElement == null)
throw new Exception("Signature element is null!");
Init.init();
XMLSignature signature = new XMLSignature(sigElement, "");
return signature.checkSignatureValue(publicKey);
}
这篇关于SOAP XML WS-Security签名验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!