在apache cxf 3.0.X中为WSS4JOutInterceptor设置EXPAND_XOP_INCLUDE

时间:2017-09-04 13:34:06

标签: java soap jax-ws cxf-client xop

我想避免在将MTOM ENABLE设置为true时自动生成apache cxf(版本3.0.4)中包含的xop,我该怎么做?例如,我有肥皂服务。它支持mtom而不支持xop包含注释,所以它拒绝了我的请求:

<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:92dc39d3-e3d5-4aa2-a9cb-7582483934a4-1@cxf.apache.org"/>**
</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:92dc39d3-e3d5-4aa2-a9cb-7582483934a4-1@cxf.apache.org"/>

cid:940325888173

怎样才能获得这个结果?在最近的版本中,这个https://ws.apache.org/wss4j/apidocs/org/apache/wss4j/common/ConfigurationConstants.html#EXPAND_XOP_INCLUDE有一个参数,我如何在旧版本中复制?

这里是我使用的java代码:

   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;              
}

1 个答案:

答案 0 :(得分:1)

我们在jboss-cxf-client的4.3.7版本中遇到了同样的问题。

似乎有几种方法可以禁用CXF,但没有一种方法可以用于我们使用的lib版本。出于文档目的,以下是对我们不起作用的各种方法:

strongSelf->_name1 = @"123";

由于CXF中存在一个错误,因此无法禁用自动转换,因此无法正常工作。解决方法是将自动转换的阈值设置为最大值。为此,请将其作为功能添加到您的端口中

// 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);

这为我们解决了这个问题。