问题描述
将MTOM ENABLE设置为true时,我想避免自动生成apache cxf(版本3.0.4)中包含的xop,我该怎么做?例如,我有一个肥皂服务.它支持mtom但不支持xop include注释,因此它拒绝了我的请求:
i want to avoid the automatic generation of the xop included from apache cxf (version 3.0.4) when set MTOM ENABLE to true how can i do that? for example, i have a soap service . it support the mtom but not the xop include annotation , so it refused my request:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>
<soap:Body>
<ns2:receiveSip xmlns:ns2="http://sip.receive.core.iris.eng.it" xmlns:xmime="http://www.w3.org/2005/05/xmlmime">
<ns2:sipReceive>
<tipoSip>?</tipoSip>
<tipoProtezione>?</tipoProtezione>
<improntaAlgoritmo>SHA-256</improntaAlgoritmo>
<improntaCodifica>HEX</improntaCodifica> <impronta>9e830c2ac56eca00023b17e3c17ed1014e055f960c3ee4778a84aa02c6dafcb9</impronta>
</ns2:sipReceive>
<arg1>
<dh>
**<xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:[email protected]"/>**
</dh>
</arg1>
</ns2:receiveSip>
</soap:Body>
</soap:Envelope>
我如何对此提出要求:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>
<soap:Body>
<ns2:receiveSip xmlns:ns2="http://sip.receive.core.iris.eng.it" xmlns:xmime="http://www.w3.org/2005/05/xmlmime">
<ns2:sipReceive>
<tipoSip>?</tipoSip>
<tipoProtezione>?</tipoProtezione>
<improntaAlgoritmo>SHA-256</improntaAlgoritmo>
<improntaCodifica>HEX</improntaCodifica> <impronta>9e830c2ac56eca00023b17e3c17ed1014e055f960c3ee4778a84aa02c6dafcb9</impronta>
</ns2:sipReceive>
<arg1>
<dh>**cid:92dc39d3-e3d5-4aa2-a9cb-7582483934a4**</dh>
</arg1>
</ns2:receiveSip>
</soap:Body>
</soap:Envelope>
所以最后我只想替换:
<xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:[email protected]"/>
使用
cid:940325888173
如何获得此结果?在最新版本中,此 https://ws.apache.org/wss4j/apidocs/org/apache/wss4j/common/ConfigurationConstants.html#EXPAND_XOP_INCLUDE ,如何在旧版本中复制?
how can obtain this result? in more recent version there is a parameter for this https://ws.apache.org/wss4j/apidocs/org/apache/wss4j/common/ConfigurationConstants.html#EXPAND_XOP_INCLUDE , how can i replicate in the older version?
这是我使用的Java代码:
Here the java code i used:
public static <T> T buildServerWsdl(String endpointWsdl,final String username,final String password,
final Class<T> serviceClass,boolean ignoreSSLCertificate,boolean useAuthorizationBasic,Map<String,String> supplierheaders) throws NoSuchAlgorithmException, KeyManagementException, MalformedURLException{
//Controllo wsdlurl
URL wsdlURL;
java.io.File wsdlFile = new java.io.File(endpointWsdl);
if (wsdlFile.exists()) {
wsdlURL = wsdlFile.toURI().toURL();
} else {
wsdlURL = new URL(endpointWsdl);
}
System.out.println(wsdlURL);
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(serviceClass);
factory.setAddress(endpointWsdl);
//Abilita il loggin in ingresco ed uscita dei messaggi soap!
factory.getInInterceptors().add(new LoggingInInterceptor(4*1024));
factory.getOutInterceptors().add(new LoggingOutInterceptor(4*1024));
@SuppressWarnings("unchecked")
T server = (T) factory.create();
// The BindingProvider interface provides access to the protocol binding and
// to the associated context objects for request and response message processing.
BindingProvider prov = (BindingProvider)server;
Binding binding = prov.getBinding();
((SOAPBinding)binding).setMTOMEnabled(true);
//Add handlers to the binding jaxb
java.util.List<javax.xml.ws.handler.Handler> handlers = binding.getHandlerChain();
handlers.add(new JaxWsLoggingHandler());
binding.setHandlerChain(handlers);
Map<String, Object> req_ctx = prov.getRequestContext();
req_ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointWsdl);
Map<String, List<String>> headers = new HashMap<String, List<String>>();
if(username != null && password != null){
headers.put("Username", Arrays.asList(username));
headers.put("Password", Arrays.asList(password));
//headers.put("Content-Type", Arrays.asList("text/xml")); //necessario specificare se si usa schema-core invece di XmlSchema
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
if(supplierheaders !=null && supplierheaders.size() > 0){
prov.getRequestContext().putAll(supplierheaders);
for(Map.Entry<String, String> entry : supplierheaders.entrySet()){
headers.put(entry.getKey(), Arrays.asList(entry.getValue()));
}
}
Authenticator myAuth = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
};
Authenticator.setDefault(myAuth);
}
if(useAuthorizationBasic){
String authorization = new sun.misc.BASE64Encoder().encode((username+":"+password).getBytes());
headers.put("Authorization", Arrays.asList("Basic " + authorization));
req_ctx.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
//MessageContext mctx = wsctx.getMessageContext();
Map<String, List<String>> http_headers = (HashMap<String, List<String>>) req_ctx.get(MessageContext.HTTP_REQUEST_HEADERS);
List list = (List) http_headers.get("Authorization");
if (list == null || list.size() == 0) {
throw new RuntimeException("Authentication failed! This WS needs BASIC Authentication!");
}
String userpass = (String) list.get(0);
userpass = userpass.substring(5);
byte[] buf = org.apache.commons.codec.binary.Base64.decodeBase64(userpass.getBytes());
String credentials = new String(buf);
String usernamex = null;
String passwordx = null;
int p = credentials.indexOf(":");
if (p > -1) {
usernamex = credentials.substring(0, p);
passwordx = credentials.substring(p+1);
}
else {
throw new RuntimeException("There was an error while decoding the Authentication!");
}
// This should be changed to a DB / Ldap authentication check
if (usernamex.equals(username) && passwordx.equals(password)) {
//System.out.println("============== Authentication Basic OK =============");
}
else {
throw new RuntimeException("Authentication failed! Wrong username / password!");
}
}
//Client cl = ClientProxy.getClient(server);
org.apache.cxf.endpoint.Client cl = org.apache.cxf.frontend.ClientProxy.getClient(server);
//=============================================================================================
// Set up WS-Security Encryption
// Reference: https://ws.apache.org/wss4j/using.html
Map<String, Object> inProps = new HashMap<String, Object>();
//props.put(ConfigurationConstants.EXPAND_XOP_INCLUDE_FOR_SIGNATURE, false);
//props.put(ConfigurationConstants.EXPAND_XOP_INCLUDE, false);
//inProps.put("expandXOPIncludeForSignature", false);
//inProps.put("expandXOPInclude", false);
//WSS4JOutInterceptor wss4jOut = new WSS4JOutInterceptor(inProps);
//ClientProxy.getClient(client).getOutInterceptors().add(wss4jOut);
//cl.getInInterceptors().add(wss4jOut);
//cl.getOutInterceptors();
//==============================================================================================
HTTPConduit httpConduit = (HTTPConduit) cl.getConduit();
//disable ssl certificate handshake
if(ignoreSSLCertificate){
String targetAddr = httpConduit.getTarget().getAddress().getValue();
if (targetAddr.toLowerCase().startsWith("https:")) {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {return new java.security.cert.X509Certificate[0];}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
} };
// Ignore differences between given hostname and certificate hostname
//HostnameVerifier hv = new HostnameVerifier(){public boolean verify(String hostname, SSLSession session) { return true; }};
TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setTrustManagers(trustAllCerts);
tlsParams.setDisableCNCheck(true);
httpConduit.setTlsClientParameters(tlsParams);
//SSLContext sc = SSLContext.getInstance("SSL");
//sc.init(null, trustAllCerts, new SecureRandom());
}
}
AuthorizationPolicy authorizationPolicy = httpConduit.getAuthorization();
authorizationPolicy.setUserName(username);
authorizationPolicy.setPassword(password);
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(10000);//10sec
httpClientPolicy.setReceiveTimeout(60000);
httpClientPolicy.setContentType("application/soap+xml");
httpConduit.setClient(httpClientPolicy);
return server;
}
推荐答案
我们在jboss-cxf-client的4.3.7版本中遇到了同样的问题.
We had the same problem with the version 4.3.7 of jboss-cxf-client.
似乎有几种方法可以禁用CXF,但没有一种方法可以用于我们使用的lib版本.出于文档目的,以下是对我们不起作用的各种方法:
There appears to be several ways to disable CXF, none of them worked for the version we used of the lib. For documentation purpose here are the various methods that did not work for us:
// Method 1
bindingProvider.getRequestContext().put("mtom-enabled", Boolean.FALSE);
bindingProvider.getRequestContext().put("write.attachments", Boolean.FALSE);
// Method 2
SOAPBinding binding = (SOAPBinding) (((BindingProvider) bindingProvider).getBinding());
binding.setMTOMEnabled(false);
由于CXF中存在一个错误,因此无法禁用自动转换,因此无法正常工作.解决方法是将自动转换的阈值设置为最大值.为此,请将其作为功能添加到您的端口中
This did not work for due to a bug in CXF which makes it impossible to disable automatic conversion. The work around was to set the threshold for automatic conversion to the maximum. To do this, add this as a feature to your port
new javax.xml.ws.soap.MTOMFeature(false, Integer.MAX_VALUE)
这为我们解决了这个问题.
This fixed the issue for us.
这篇关于在apache cxf 3.0.X中为WSS4JOutInterceptor设置EXPAND_XOP_INCLUDE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!