2
votes

I am facing getting SSLhandshakeException while I try to consume a CXF webservice using a CXF client over HTTPS connection.

The web service requires SSL connection therefore I have PKCS 12 key store which is referenced in the java code directly with the password as below.

System property configuration in java code:

System.setProperty("javax.net.ssl.keyStore", "/home/user/test-client.p12");  
System.setProperty("javax.net.ssl.keyStorePassword", "AbcgfhYgb");
System.setProperty("javax.net.debug", "ssl, handshake");

CXF client configuration in cxf.xml

<jaxws:client id="CService" serviceClass="com..cws.CService"
        address="https://developer.webservice.com/test" />

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

Exception Thrown on executing the client

Caused by: javax.net.ssl.SSLHandshakeException: SSLHandshakeException invoking https://developer.webservice.com/test: Received fatal alert: handshake_failure
                at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
                at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
                at java.lang.reflect.Constructor.newInstance(Constructor.java:534)
                at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.mapException(HTTPConduit.java:1338)
                at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1322)
                at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:50)
                at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:223)
                at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
                at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:622)
                at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
                at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
                at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:530)
                at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:463)
                at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:366)
                at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:319)
                at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
                at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:133)
                ... 53 more
        Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
                at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
                at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
                at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1748)
                at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:991)
                at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1175)
                at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1202)
                at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1186)
                at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:440)
                at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
                at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:979)
                at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
                at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.setupWrappedStream(URLConnectionHTTPConduit.java:168)
                at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1282)
                at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1233)
                at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.onFirstWrite(URLConnectionHTTPConduit.java:195)
                at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47)
                at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:69)
                at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1295)
                ... 65 more

Can anyone suggest solution for accessing the web service using CXF client with SSL.

2
Unfortunately, the documentation on creating a CXF-based client leaves something to be desired and the few sources that I could find on the web describe different ways to do this. Yours is yet another one, as it references the SSL certificate via System.setProperty() instead of using the formal Apache approach via <http:conduit. I am facing similar difficulties here, perhaps you could get an idea from my approach (which is throwing a different type of exception and I haven't solved this yet). - Withheld

2 Answers

0
votes

Reference the JDK cacerts as a trustore manager which consist of the CA certificate for the SSL certificate. Also, add the keystore which consist of the SSL certifcate as below.

     <http-conf:conduit name="*.http-conduit">
    <http-conf:tlsClientParameters>
        <sec:keyManagers keyPassword="testkey">
            <sec:keyStore type="JKS" password="changeit"
                file="<keystore path>" />
        </sec:keyManagers>
        <sec:trustManagers>
            <sec:keyStore type="JKS" password="changeit"
                file="<cacert path>" />
        </sec:trustManagers>
    </http-conf:tlsClientParameters>
    <http-conf:client AutoRedirect="true" Connection="Keep-Alive" />
</http-conf:conduit>
0
votes

Below configuration will enable CXF client to consume JAXWS service over SSL ( https):

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

Check: 1. That certificate has been impoprted in the consumer for producer 2. Additionlay if you have a problem where there is a mismatch between hostname and the one in certificate you can use disableCNCheck="true". However this flag is not recomended for Producation