KSOAP 2 Android with HTTPS

27,356

Solution 1

I can't comment yet so i post my comments to rallat answer here. His solution works but it needs further explanations. To run ksoap2 with ssl:

  1. Put ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar in a project
  2. Download ksoap2 sources from https://github.com/mosabua/ksoap2-android/tree/ (ksoap2 repository)
  3. Copy HttpTransportSE.java, ServiceConnectionSE.java (I also needed to copy Transport.java, ServiceConnection.java and HeaderProperty.java). Delete imports from those files and make sure that they use your files (not imports from ksoap2.jar)
  4. Use rallat answer ( I copy-pasted it):

    • ServiceConnectionSE.java add this for accept untrusted certificate:

      private TrustManager[] trustAllCerts = new TrustManager[] {
          new X509TrustManager() {
              public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                  return null;
              }
              public void checkClientTrusted(
                  java.security.cert.X509Certificate[] certs, String authType) {
              }
              public void checkServerTrusted(
                  java.security.cert.X509Certificate[] certs, String authType) {
              }
          }
      };
      
    • then use this constructors to allow untrusted certificates and not verified hostnames:

      public ServiceConnectionSE(String url) throws IOException {
          try {
              SSLContext sc = SSLContext.getInstance("TLS");
              sc.init(null, trustAllCerts, new java.security.SecureRandom());
              HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
          } catch (Exception e) {
              e.getMessage();
          }
          connection = (HttpsURLConnection) new URL(url).openConnection();
          ((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
      }    
      
    • Second contructor

      public ServiceConnectionSE(Proxy proxy, String url) throws IOException {
          try {
              SSLContext sc = SSLContext.getInstance("TLS");
              sc.init(null, trustAllCerts, new java.security.SecureRandom());
              HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
           } catch (Exception e) {
              e.getMessage();
           }
           connection = (HttpsURLConnection) new URL(url).openConnection();
          ((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
      
          connection.setUseCaches(false);
          connection.setDoOutput(true);
          connection.setDoInput(true);
      }
      
  5. In your code just use:

    HttpTransportSE aht = new HttpTransportSE(URL);    
    aht.call(SOAP_ACTION, envelope);
    

Other things as in tutorials

Solution 2

Checking again this problem, I've discovered a more clean solution for me. No KSOAP2 files modification needed.

In your project, link the ksoap2-android-assembly-3.0.0-jar, with no modifications.

Next, create a file named SSLConnection.java with this code:

package com.example.mypackage;

import android.util.Log;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class SSLConection {

    private static TrustManager[] trustManagers;

    public static class _FakeX509TrustManager implements javax.net.ssl.X509TrustManager {
        private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};

        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return (_AcceptedIssuers);
        }
    }

    public static void allowAllSSL() {

        javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });

        javax.net.ssl.SSLContext context;

        if (trustManagers == null) {
            trustManagers = new TrustManager[]{new _FakeX509TrustManager()};
        }

        try {
            context = javax.net.ssl.SSLContext.getInstance("TLS");
            context.init(null, trustManagers, new SecureRandom());
            javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
        } catch (NoSuchAlgorithmException e) {
            Log.e("allowAllSSL", e.toString());
        } catch (KeyManagementException e) {
            Log.e("allowAllSSL", e.toString());
        }
    }
}

And just call to SSLConection.allowAllSSL(); before calling a server method via KSOAP2. It's all, works for me. All SSL certificates are accepted and I can use KSOAP2 with https protocol.

Solution 3

Create a new class FakeX509TrustManager to handle the certificate problem,

    FakeX509TrustManager.allowAllSSL();
    HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

The new created class is as the following:

public class FakeX509TrustManager implements X509TrustManager { 

    private static TrustManager[] trustManagers; 
    private static final X509Certificate[] _AcceptedIssuers = new 
X509Certificate[] {}; 

    @Override 
    public void checkClientTrusted(X509Certificate[] chain, String 
authType) throws CertificateException { 
    } 

    @Override 
    public void checkServerTrusted(X509Certificate[] chain, String 
authType) throws CertificateException { 
    } 

    public boolean isClientTrusted(X509Certificate[] chain) { 
            return true; 
    } 

    public boolean isServerTrusted(X509Certificate[] chain) { 
            return true; 
    } 

    @Override 
    public X509Certificate[] getAcceptedIssuers() { 
            return _AcceptedIssuers; 
    } 

    public static void allowAllSSL() { 
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() 
{ 
                    @Override 
                    public boolean verify(String hostname, SSLSession session) { 
                            return true; 
                    } 

            }); 

            SSLContext context = null; 
            if (trustManagers == null) { 
                    trustManagers = new TrustManager[] { new FakeX509TrustManager() }; 
            } 

            try { 
                    context = SSLContext.getInstance("TLS"); 
                    context.init(null, trustManagers, new SecureRandom()); 
            } catch (NoSuchAlgorithmException e) { 
                    e.printStackTrace(); 
            } catch (KeyManagementException e) { 
                    e.printStackTrace(); 
            } 

       HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory()); 
    } 

} 

Solution 4

I find the answer by myself

  • on ServiceConnectionSE.java add this for accept untrusted certificate:

    private TrustManager[] trustAllCerts = new TrustManager[]{
        new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
            }
        }
    };
    
  • then in the constructor add this to allow untrusted certificates and not verified hostnames:

        try {
           SSLContext sc = SSLContext.getInstance("TLS");
           sc.init(null, trustAllCerts, new java.security.SecureRandom());
           HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
           e.getMessage();
        }
        connection = (HttpsURLConnection) new URL(url).openConnection();
        ((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
    
Share:
27,356
rallat
Author by

rallat

Android developer at Lookout.com

Updated on September 24, 2020

Comments

  • rallat
    rallat over 3 years

    I am using KSOAP2 to manage SOAP in Android but it use https for the SOAP url and I am getting this error: javax.net.ssl.SSLException: Not trusted server certificate
    A normal error because the certificate is untrusted, but anyone knows how to workaround with this error? I can not manage the certificate because is from a other company and I don't have access to change it.

    Thanks

  • Amritpal Singh
    Amritpal Singh about 11 years
    @Zirael...Thanks for ur anwser it helped...I was eager to know rather than working around if Had the Security Certificate...How do i proceed further with it..?
  • whyoz
    whyoz almost 11 years
    Serious +1 jowett...I put your code at the end of my activity and all I had to do was make the FakeX509TrustManager static and it got right through...I've read a more than a few SO posts and this was the easiest to implement by far. Notice the dates on the previous answers in this post...enough said. Do you have any resources on the easiest way to NOT trust all certs for production code?
  • rallat
    rallat over 10 years
    Thanks for adding your snippet too
  • JustADev
    JustADev over 10 years
    Perfect simple solution! Thank you :)
  • micnoy
    micnoy about 10 years
    Can't find the sources of ksoap using the provided link - its broken. =\ update: I found it... just use :github.com/mosabua/ksoap2-android
  • jowett
    jowett over 9 years
    @whyoz sorry, no resource.
  • amitavk
    amitavk over 8 years
    This is a very dangerous workaround though. Leaves you exposed to MITM attacks.
  • Admin
    Admin almost 4 years
    How can i include ssl in ksoap2 ? Can you check - stackoverflow.com/questions/62006180/…