Question

I am having a problem here since ytday in fact. I am trying to load a jar file dynamically at runtime over https url - and i can't figure out how to exactly do it. I am able to load the jar over standard http: url but not when using https:

public void addURL(URL https) throws IOException {
    HttpsURLConnection conn = (HttpsURLConnection) https.openConnection();


    Class<?>[] parameters = new Class[]{URL.class}; 
    log.info("https url : " + https);


    // IMPORTANT: MUST use the webapp classloader - so derived extension classes car esolve their base classes
    ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();        
    // cast to a URL class loader so we can additional JAR(s) to the search path
    URLClassLoader webappClassLoader = (URLClassLoader)contextClassLoader;  
    Class<?> sysclass = URLClassLoader.class;

    Method method;
    try {
        method = sysclass.getDeclaredMethod("addURL", parameters);
        method.setAccessible(true);
        method.invoke(webappClassLoader, new Object[]{ https });
    } catch (NoSuchMethodException | SecurityException e) {
        e.printStackTrace();
    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        e.printStackTrace();
    }
}

Help much appreciated :) in pointing / showing me where or what to add etc.

Was it helpful?

Solution

Since you are dealing with Secure Connections, you are stepping into the area of Certificates.

Java thinks that your Server is not trusted. You could understand that from the stack traces.

You have two choices here. You can let your program to ignore the Certificate Validation. You will need to execute this code only once before you call addURL.

import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.*;

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

                public void checkClientTrusted(X509Certificate[] certs, String t)
                {
                }

                public void checkServerTrusted(X509Certificate[] certs, String t)
                {
                }
            }
        };
    return certs;
}


SSLContext sslCtx = SSLContext.getInstance("SSL");
TrustManager trustManager[] = getBypassingTrustManager();
sslCtx.init(null, trustManager, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslCtx.getSocketFactory());

The above approach is not great in the sense of Security. Far better if you learn how Java Keystores work (java.security.KeyStore). Instead of ignoring Certificate Validation, you can keep the Certificate from your Server in a Keystore file. Your application can then load your keystore, which makes Java trusting your Servers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top