我正在将应用程序升级到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)
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");
}
}
答案 0 :(得分:5)
显然,spring引入了wss4j-ws-security-dom中的一个错误。2.2.0。
我更新到最新的版本2.2.2,并且有效:
答案 1 :(得分:2)
也可以降级到2.0.6并开始工作。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
<version>2.0.6.RELEASE</version>
</dependency>
答案 2 :(得分:0)
与新版本的saaj-impl(v1.4.0或更高版本)一起使用时,也会出现问题。
<dependency>
<groupId>com.sun.xml.messaging.saaj</groupId>
<artifactId>saaj-impl</artifactId>
<version>1.3.28</version>
</dependency>