Finally, I've discovered there is a bug in wss4j.
Debugging the code, I've found that WSHandler, for my purpose, mainly uses two other classes: WSSecUsernameToken and WSSecurityUtil. The last one is intended to work with DOM objects and SOAP Security Headers.
The code execution flow is:
WSSecUsernameToken
Code:
public Document build(Document doc, WSSecHeader secHeader) {
log.debug("Begin add username token...");
prepare(doc);
prependToHeader(secHeader);
return doc;
}
and prependToHeader method calls:
Code:
WSSecurityUtil.prependChildElement(document, secHeader.getSecurityHeader(), ut.getElement(), false);
and then, the WSSecurityUtil.prependChildElement code is:
Code:
public static Element prependChildElement(Document doc, Element parent,
Element child, boolean addWhitespace) {
Node firstChild = parent.getFirstChild();
if (firstChild == null) {
parent.appendChild(child);
} else {
parent.insertBefore(child, firstChild);
}
if (addWhitespace) {
Node whitespaceText = doc.createTextNode("\n");
parent.insertBefore(whitespaceText, child);
}
return child;
}
In the execution, the doc is the SOAPMessage, the parent is the SecurityHeader DOM element and the child is the UserNameToken DOM element.
It's a bit difficult, but if you pay attention to the execution, there's a separation of concerns between the WSSecHeader passed to UserNameTokenAction and the doc that represents the SOAP message. So, although the last method builds a good security DOM element
Code:
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<wsse:UsernameToken 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:Id="UsernameToken-5764479">
<wsse:Username xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">userName</wsse:Username>
<wsse:Password xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">1111</wsse:Password>
<wsse:Nonce xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">uzL0ydaZc0vcdN3WoQxSzw==</wsse:Nonce>
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2008-12-10T17:33:08.750Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
the document (the SOAP Message) doesn't refresh its Security header, because those objects are different and disconnected.
So, finally, it's a wss4j bug.
I change my wss4j code to resolve the use case, but I think it's not a general purpose solution, so I prefer not to mention it here.
What's the policy when someone find a bug in another system (wss4j in this case), and it affects the features of Spring? (In the Spring reference, you offer the feature as if it works)