使用Wss4jSecurityInterceptor会抛出WRONG_DOCUMENT_ERR:与创建该节点的节点不同的节点用于另一文档中

tob*_*tob 5 java soap-client spring-boot

我正在将应用程序升级到Java 11和Spring boot 2.1.2,并在尝试通过SOAP与外部合作伙伴通信时遇到以下错误。导致此问题的原因是Wss4jSecurityInterceptor。在运行Java 8和Spring Boot 1之前可以工作

REQUEST: ExampleSoapClient.sendRequest([javax.xml.bind.JAXBElement@5bba179f]). 
ERROR: WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it.
org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it.
at java.xml/com.sun.org.apache.xerces.internal.dom.ParentNode.internalInsertBefore(ParentNode.java:356)
at java.xml/com.sun.org.apache.xerces.internal.dom.ParentNode.insertBefore(ParentNode.java:287)
at java.xml/com.sun.org.apache.xerces.internal.dom.NodeImpl.appendChild(NodeImpl.java:237)
at org.apache.wss4j.dom.util.WSSecurityUtil.prependChildElement(WSSecurityUtil.java:314)
at org.apache.wss4j.dom.util.WSSecurityUtil.findWsseSecurityHeaderBlock(WSSecurityUtil.java:435)
at org.apache.wss4j.dom.message.WSSecHeader.insertSecurityHeader(WSSecHeader.java:165)
at org.apache.wss4j.dom.handler.WSHandler.doSenderAction(WSHandler.java:117)
at org.springframework.ws.soap.security.wss4j2.Wss4jHandler.doSenderAction(Wss4jHandler.java:63)
at org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor.secureMessage(Wss4jSecurityInterceptor.java:574)
at org.springframework.ws.soap.security.AbstractWsSecurityInterceptor.handleRequest(AbstractWsSecurityInterceptor.java:210)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:597)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:378)
at com.example.domain.integration.provider.ExampleSoapClient.sendRequest(ExampleportSoapClient.java:61)
Run Code Online (Sandbox Code Playgroud)

Java 11和Spring Boot 2.1.2升级

import com.sun.xml.wss.impl.callback.PasswordCallback;
import com.sun.xml.wss.impl.callback.UsernameCallback;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor;
import org.springframework.ws.transport.http.ClientHttpRequestMessageSender;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;

public class ExampleSoapClient extends WebServiceGatewaySupport {

private Wss4jSecurityInterceptor wss4jSecurityInterceptor;

public ExampleSoapClient(Wss4jSecurityInterceptor wss4jSecurityInterceptor) {
    wss4jSecurityInterceptor = new Wss4jSecurityInterceptor();
    wss4jSecurityInterceptor.setValidationCallbackHandler(new ExampleCredentialsCallbackHandler());
    wss4jSecurityInterceptor.setSecurementActions(WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.USERNAME_TOKEN);
    /* Default Password encoding is digest, that is not supported by EP hence need to set need to set following password type. */
    wss4jSecurityInterceptor.setSecurementPasswordType(WSConstants.PASSWORD_TEXT);
    wss4jSecurityInterceptor.setSecurementUsernameTokenNonce(false);
    wss4jSecurityInterceptor.setSecurementUsername("username");
    wss4jSecurityInterceptor.setSecurementPassword("password");
    //Note! this will help our external mock to not need any security implementation
    wss4jSecurityInterceptor.setSecurementMustUnderstand(false);

    SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
    requestFactory.setConnectTimeout(40000);
    requestFactory.setReadTimeout(40000);
    setMessageSender(new ClientHttpRequestMessageSender(requestFactory));
}

public Object sendRequest(Object request) {

    final WebServiceTemplate webServiceTemplate = getWebServiceTemplate();
    ClientInterceptor[] interceptors = new ClientInterceptor[1];

    interceptors[0] = wss4jSecurityInterceptor;
    webServiceTemplate.setInterceptors((interceptors));

    final SubmitDocument submitDocument = createRequest(request);

    final SubmitDocumentResponse submitDocumentResponse = (SubmitDocumentResponse) webServiceTemplate.marshalSendAndReceive(endpoint, submitDocument);
    return response;
}

}
class ExampleCredentialsCallbackHandler implements CallbackHandler {

public ExampleCredentialsCallbackHandler() {
}

@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

    for (Callback callback : callbacks) {

        if (callback instanceof UsernameCallback) {
            handleUsernameCallback((UsernameCallback) callback);
        } else if (callback instanceof PasswordCallback) {
            handlePasswordCallback((PasswordCallback) callback);
        } else {
            throw new UnsupportedCallbackException(callback);
        }
    }
}

private void handleUsernameCallback(UsernameCallback callback) {
    callback.setUsername("username");
}

private void handlePasswordCallback(PasswordCallback callback) {
    callback.setPassword("password");
}
Run Code Online (Sandbox Code Playgroud)

}

小智 10

与新版本 saaj-impl(v1.4.0 或更高版本)一起使用时也存在问题。

<dependency>
    <groupId>com.sun.xml.messaging.saaj</groupId>
    <artifactId>saaj-impl</artifactId>
    <version>1.3.28</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)


tob*_*tob 8

显然,spring引入了wss4j-ws-security-dom中的一个错误。2.2.0。

我更新到最新的版本2.2.2,并且有效: