I want to add wsse:security to my soap message. This is my code:
public Document signSoapMessage(SOAPMessage message) {
try {
Document doc = message.getSOAPBody().getOwnerDocument();
Crypto crypto = CryptoFactory.getInstance(properties); //File
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
InputStream inStream = new FileInputStream(properties.getProperty("org.apache.ws.security.crypto.merlin.keystore.file"));
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(inStream, properties.getProperty("privatekeypassword").toCharArray());
String alias = ks.aliases().nextElement();
X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
WSSecSignature sign = new WSSecSignature(secHeader);
sign.setX509Certificate(cert);
sign.setUserInfo(properties.getProperty("org.apache.ws.security.crypto.merlin.keystore.alias"), properties.getProperty("privatekeypassword"));
sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE); // Binary Security Token - SecurityTokenReference
sign.setUseSingleCertificate(true);
sign.setDigestAlgo(DigestMethod.SHA1);
//sign.build(crypto);
Document signedDoc = sign.build(crypto);
return signedDoc;
} catch (SOAPException e) {
e.printStackTrace();
return null;
} catch (WSSecurityException e) {
e.printStackTrace();
throw new RuntimeException("Error: " + e.getMessage());
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (CertificateException e) {
e.printStackTrace();
return null;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (KeyStoreException e) {
e.printStackTrace();
return null;
}
}
It works for soapenv:Body (It does add wsu:Id and xmlns:wsu parameters)
But there is an extra element in soapenv:Header and it doesn't sign this element. There is no wsu:Id and xmlns:wsu parameters and lack of one ds:Reference.
Example of not signed soap msg:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<!-- this element should be signed but is not - NOT WORKING -->
<something>
</something>
</soapenv:Header>
<!-- this element should be signed and It does. -->
<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>
I compare soap msg from my program to working soap msg from SoapUI project.
When I post a message to web service I get an error: wsse:InvalidSecurity - Soap Header must be signed
. While in SoupUI it does works.
So my question is how can I force WSS4j to sign extra element inside soapenv:Header ?