Search code examples
javassl-certificatecxfwildflysoap-client

Disable certificate check in SAAJ Soap Connection


Java EE application where there is a SOAP call using SoapClient object (deployed in Wildfly 9):

SOAPMessage reply = con.call(message, url);

I am receiving following message:

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.setupWrappedStream(URLConnectionHTTPConduit.java:183)

Due to certificate problems, tried to bypass the error:

    TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                    return;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                    return;
                }
            }
    };     
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());


    soapConnectionFactory = SOAPConnectionFactory.newInstance();

This didn´t have any effect

Any ideas?


Solution

  • If CXF is you client framework, then it does not use the default HTTP Socket factory, but its own.

    Therefore, I advise you to use the CXF configuration tools as described in the CXF manual and the TLS parameters configuration

    It boils down to creating a conduit for your particular endpoint and setting its parameters, for example to set a configuration for a endpoint on the HelloWorld namespace :

    <http:conduit name="{http://apache.org/hello_world}HelloWorld.http-conduit">
    <http:tlsClientParameters>
      <sec:trustManagers>
        <sec:keyStore type="JKS" password="password"
                      file="my/file/dir/Truststore.jks"/>
      </sec:trustManagers>
    </http:tlsClientParameters>
    

    Note that you can set a SSLSocketFactory instead of a keystore (see second link above) :

    Client TLS Parameters : sslSocketFactory > A SSLSocketFactory to use. All other bean properties are ignored if this is set.

    If you do not wish to use XML / Spring configuration, you can resort to programmatic calls, by taping into the CXF API :

    How to configure the HTTPConduit for the SOAP Client?
    First you need get the HTTPConduit from the Proxy object or Client, then you can set the HTTPClientPolicy, AuthorizationPolicy, ProxyAuthorizationPolicy, TLSClientParameters, and/or HttpBasicAuthSupplier.

    import org.apache.cxf.endpoint.Client;
    import org.apache.cxf.frontend.ClientProxy;
    import org.apache.cxf.transport.http.HTTPConduit;
    import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
    ...
    
    URL wsdl = getClass().getResource("wsdl/greeting.wsdl");
    SOAPService service = new SOAPService(wsdl, serviceName);
    Greeter greeter = service.getPort(portName, Greeter.class);
    
    // Okay, are you sick of configuration files 
     // This will show you how to configure the http conduit dynamically
    Client client = ClientProxy.getClient(greeter);
    HTTPConduit http = (HTTPConduit) client.getConduit();
    
    HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
    
    httpClientPolicy.setConnectionTimeout(36000);
    httpClientPolicy.setAllowChunking(false);
    httpClientPolicy.setReceiveTimeout(32000);
    
    http.setClient(httpClientPolicy);
    
    ...
      greeter.sayHi("Hello");
    

    You can also check this SO answer How to programmatically set the SSLContext of a JAX-WS client? that has solutions for CXF and non CXF cases.

    You may want to look at this solution in particular :

    <http-conf:conduit name="*.http-conduit">
      <http-conf:tlsClientParameters useHttpsURLConnectionDefaultSslSocketFactory="true" />
    <http-conf:conduit>