无法使用 Apache CXF 客户端从 WS 服务接收回消息:读取超时
Could not receive message back from WS service using Apache CXF Client: Read time out
我正在尝试调用基于 IIS WPF 的 Web 服务,其 WSDL 具有以下策略:
<wsp:Policy wsu:Id="custom_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy/>
</sp:Wss11>
<sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:MustSupportIssuedTokens/>
<sp:RequireClientEntropy/>
<sp:RequireServerEntropy/>
</wsp:Policy>
</sp:Trust10>
<wsaw:UsingAddressing/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
使用 Apache CXF 客户端和以下代码:
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(ITerytWs1.class);
factory.setAddress("https://uslugaterytws1test.stat.gov.pl/terytws1.svc");
ITerytWs1 info = (ITerytWs1) factory.create();
Map ctx = ((BindingProvider)info).getRequestContext();
ctx.put("ws-security.username", "TestPubliczny");
ctx.put("ws-security.password", "1234abcd");
ctx.put("ws-security.callback-handler", ClientPasswordCallback.class.getName());
var zal = info.isLoggedIn();
依赖项是:
compile group: 'org.apache.cxf', name: 'cxf-rt-frontend-jaxws', version: '3.3.7'
compile group: 'org.apache.cxf', name: 'cxf-rt-transports-http', version: '3.3.7'
compile group: 'com.sun.activation', name: 'javax.activation', version: '1.2.0'
compile group: 'org.apache.cxf', name: 'cxf-rt-ws-security', version: '3.3.7'
compile group: 'com.sun.xml.messaging.saaj', name: 'saaj-impl', version: '1.5.2'
我只收到读取超时:
lip 16, 2020 1:58:31 PM org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging
WARNING: Interceptor for {http://tempuri.org/}ITerytWs1Service#{http://tempuri.org/}CiekawostkiSIMC has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: Could not receive Message.
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:65)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:530)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:441)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:356)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:314)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
[...]
Caused by: java.net.SocketTimeoutException: SocketTimeoutException invoking https://uslugaterytws1test.stat.gov.pl/terytws1.svc: Read timed out
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[..]
Caused by: java.net.SocketTimeoutException: Read timed out
at java.base/java.net.SocketInputStream.socketRead0(Native Method)
[...]
Could not receive Message.
javax.xml.ws.WebServiceException: Could not receive Message.
at org.apache.cxf.jaxws.JaxWsClientProxy.mapException(JaxWsClientProxy.java:183)
[...]
原因:java.net.SocketTimeoutException:调用 SocketTimeoutException https://uslugaterytws1test.stat.gov.pl/terytws1.svc:读取超时
在 java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法)
[...]
这个WS policy怎么配置正确,是客户端的问题还是其他的?
我必须使用 SoapUI 检查发送给服务的信封类型以获得正确答案,然后我必须对代码执行相同的操作。之前的问题是错误的请求被发送到服务器并且服务器得到内部异常(可能)并且没有返回错误请求的答案。
这是我对class所做的:
import lombok.Getter;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.ws.addressing.WSAddressingFeature;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.tempuri.ITerytWs1;
import javax.inject.Inject;
import java.util.HashMap;
import java.util.Map;
public class WebServiceClient {
@Getter
private ITerytWs1 service;
private final ApiClientConfiguration apiClientConfiguration;
private final ClientPasswordCallback clientPasswordCallback;
@Inject
public WebServiceClient(ApiClientConfiguration apiClientConfiguration) {
this.apiClientConfiguration = apiClientConfiguration;
this.clientPasswordCallback = new ClientPasswordCallback(apiClientConfiguration);
initializeService();
configureService();
}
private void configureService() {
var client = ClientProxy.getClient(service);
var endpoint = client.getEndpoint();
Map<String, Object> outInterceptorProperties = createOutInterceptorProperties();
var wssOutInterceptor = new WSS4JOutInterceptor(outInterceptorProperties);
endpoint.getOutInterceptors().add(wssOutInterceptor);
}
private void initializeService() {
var factory = new JaxWsProxyFactoryBean();
var wsAddressingFeature = new WSAddressingFeature();
factory.getFeatures().add(wsAddressingFeature);
factory.setServiceClass(ITerytWs1.class);
factory.setAddress(apiClientConfiguration.getAddress());
service = (ITerytWs1) factory.create();
}
private Map<String, Object> createOutInterceptorProperties() {
Map<String,Object> outInterceptorProperties = new HashMap<>();
outInterceptorProperties.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outInterceptorProperties.put(WSHandlerConstants.USER, apiClientConfiguration.getUsername());
outInterceptorProperties.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
outInterceptorProperties.put(WSHandlerConstants.ADD_USERNAMETOKEN_NONCE, "true");
outInterceptorProperties.put(WSHandlerConstants.ADD_USERNAMETOKEN_CREATED, "true");
outInterceptorProperties.put(WSHandlerConstants.MUST_UNDERSTAND, "false");
// Callback used to retrieve password for given user.
outInterceptorProperties.put(WSHandlerConstants.PW_CALLBACK_REF, clientPasswordCallback);
return outInterceptorProperties;
}
}
我正在尝试调用基于 IIS WPF 的 Web 服务,其 WSDL 具有以下策略:
<wsp:Policy wsu:Id="custom_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy/>
</sp:Wss11>
<sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:MustSupportIssuedTokens/>
<sp:RequireClientEntropy/>
<sp:RequireServerEntropy/>
</wsp:Policy>
</sp:Trust10>
<wsaw:UsingAddressing/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
使用 Apache CXF 客户端和以下代码:
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(ITerytWs1.class);
factory.setAddress("https://uslugaterytws1test.stat.gov.pl/terytws1.svc");
ITerytWs1 info = (ITerytWs1) factory.create();
Map ctx = ((BindingProvider)info).getRequestContext();
ctx.put("ws-security.username", "TestPubliczny");
ctx.put("ws-security.password", "1234abcd");
ctx.put("ws-security.callback-handler", ClientPasswordCallback.class.getName());
var zal = info.isLoggedIn();
依赖项是:
compile group: 'org.apache.cxf', name: 'cxf-rt-frontend-jaxws', version: '3.3.7'
compile group: 'org.apache.cxf', name: 'cxf-rt-transports-http', version: '3.3.7'
compile group: 'com.sun.activation', name: 'javax.activation', version: '1.2.0'
compile group: 'org.apache.cxf', name: 'cxf-rt-ws-security', version: '3.3.7'
compile group: 'com.sun.xml.messaging.saaj', name: 'saaj-impl', version: '1.5.2'
我只收到读取超时:
lip 16, 2020 1:58:31 PM org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging
WARNING: Interceptor for {http://tempuri.org/}ITerytWs1Service#{http://tempuri.org/}CiekawostkiSIMC has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: Could not receive Message.
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:65)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:530)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:441)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:356)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:314)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
[...]
Caused by: java.net.SocketTimeoutException: SocketTimeoutException invoking https://uslugaterytws1test.stat.gov.pl/terytws1.svc: Read timed out
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[..]
Caused by: java.net.SocketTimeoutException: Read timed out
at java.base/java.net.SocketInputStream.socketRead0(Native Method)
[...]
Could not receive Message.
javax.xml.ws.WebServiceException: Could not receive Message.
at org.apache.cxf.jaxws.JaxWsClientProxy.mapException(JaxWsClientProxy.java:183)
[...] 原因:java.net.SocketTimeoutException:调用 SocketTimeoutException https://uslugaterytws1test.stat.gov.pl/terytws1.svc:读取超时 在 java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法) [...]
这个WS policy怎么配置正确,是客户端的问题还是其他的?
我必须使用 SoapUI 检查发送给服务的信封类型以获得正确答案,然后我必须对代码执行相同的操作。之前的问题是错误的请求被发送到服务器并且服务器得到内部异常(可能)并且没有返回错误请求的答案。
这是我对class所做的:
import lombok.Getter;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.ws.addressing.WSAddressingFeature;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.tempuri.ITerytWs1;
import javax.inject.Inject;
import java.util.HashMap;
import java.util.Map;
public class WebServiceClient {
@Getter
private ITerytWs1 service;
private final ApiClientConfiguration apiClientConfiguration;
private final ClientPasswordCallback clientPasswordCallback;
@Inject
public WebServiceClient(ApiClientConfiguration apiClientConfiguration) {
this.apiClientConfiguration = apiClientConfiguration;
this.clientPasswordCallback = new ClientPasswordCallback(apiClientConfiguration);
initializeService();
configureService();
}
private void configureService() {
var client = ClientProxy.getClient(service);
var endpoint = client.getEndpoint();
Map<String, Object> outInterceptorProperties = createOutInterceptorProperties();
var wssOutInterceptor = new WSS4JOutInterceptor(outInterceptorProperties);
endpoint.getOutInterceptors().add(wssOutInterceptor);
}
private void initializeService() {
var factory = new JaxWsProxyFactoryBean();
var wsAddressingFeature = new WSAddressingFeature();
factory.getFeatures().add(wsAddressingFeature);
factory.setServiceClass(ITerytWs1.class);
factory.setAddress(apiClientConfiguration.getAddress());
service = (ITerytWs1) factory.create();
}
private Map<String, Object> createOutInterceptorProperties() {
Map<String,Object> outInterceptorProperties = new HashMap<>();
outInterceptorProperties.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outInterceptorProperties.put(WSHandlerConstants.USER, apiClientConfiguration.getUsername());
outInterceptorProperties.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
outInterceptorProperties.put(WSHandlerConstants.ADD_USERNAMETOKEN_NONCE, "true");
outInterceptorProperties.put(WSHandlerConstants.ADD_USERNAMETOKEN_CREATED, "true");
outInterceptorProperties.put(WSHandlerConstants.MUST_UNDERSTAND, "false");
// Callback used to retrieve password for given user.
outInterceptorProperties.put(WSHandlerConstants.PW_CALLBACK_REF, clientPasswordCallback);
return outInterceptorProperties;
}
}