Search code examples
javasslhttpswsdljax-ws

Creating a Service against a generated web client with a https WSDL


So I have to create a service against a WSDL hosted at a HTTPS url and am having trouble creating the service. For practical reasons I am not allowed to add the cert to my trust store so when I do the following steps with a custom SSLSocketFactory(So we can dynamically change the keystore):

QName name = new QName(qName, QNAME);
Service service = new Client(httpsUrl, name);
port = service.getPort(ClientSoap.class);

We get the familiar error of

unable to find valid certification path to requested target

A work around for this is to add the custom socket factory before we create the service, so our SSL context is correct (as detailed here 1)

HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);

However this then pollutes the default SSLContext of the application to our specific custom context and causes other https calls within the app to fail, as they are using our just used, custom context instead of the cacerts one.

Is there any way when we initially create the service to use our custom context then and only then?


Solution

  • OK I solved this myself by doing something a bit ugly(IMO) but I thought I'd put it here in case anyone else runs into this issue. Essentially pull the original SSLContext into a class level variable, then set the default with the new context. After all processing is done reset the default context to the original one.

    private SSLSocketFactory originalSocketFactory;
    private SSLSocketFactory customSocketFactory;
    
    public void doSomeStuff(){
    
        try {
            setSocketFactories();
        } catch (CertificateException | IOException | GeneralSecurityException e) {
            e.printStackTrace();
        }
    
        //do your stuff here
    
        resetOriginalSocketFactory();
    }
    
    private void setSocketFactories() throws CertificateException, IOException, GeneralSecurityException {
    
        String jksFile = "C:\\My.jks";
        String type = "JKS";
        String password="password";
    
        if(null == originalSocketFactory){
            originalSocketFactory= HttpsURLConnection.getDefaultSSLSocketFactory();         
        }
        if(null == customSocketFactory){
            customSocketFactory = getCustomSocketFactory(jksFile, type, password);
            HttpsURLConnection.setDefaultSSLSocketFactory(customSocketFactory);
        }
    }
    
    private void resetOriginalSocketFactory(){
        HttpsURLConnection.setDefaultSSLSocketFactory(originalSocketFactory);
    }
    
    private SSLSocketFactory getCustomSocketFactory(String keyStoreLocation, String keystoreType,String password) 
            throws CertificateException, IOException, GeneralSecurityException {
        SSLSocketFactory socketFactory = new SSLSocketFactoryGenerator(keyStoreLocation,keystoreType).getSSLSocketFactory(password);
        return socketFactory;
    }