2010-08-09 16 views
12

Sto usando KSOAP2 per gestire SOAP in Android ma usa https per l'URL SOAP e sto ricevendo questo errore: javax.net.ssl.SSLException: Certificato server non attendibile
Un errore normale perché il certificato non è attendibile, ma qualcuno sa come ovviare a questo errore? Non riesco a gestire il certificato perché proviene da un'altra azienda e non ho accesso per cambiarlo.KSOAP 2 Android con HTTPS

Grazie

risposta

10

Non riesco ancora a commentare quindi invio i miei commenti alla risposta rallat qui. La sua soluzione funziona ma necessita di ulteriori spiegazioni. Per eseguire ksoap2 con SSL:

  1. Metti ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar in un progetto
  2. fonti Scarica ksoap2 da https://github.com/mosabua/ksoap2-android/tree/ (repository ksoap2)
  3. Copia HttpTransportSE.java, ServiceConnectionSE.java (Ho anche bisogno di copiare Transport.java, ServiceConnection.java e HeaderProperty.java).Eliminare le importazioni da quei file e fare in modo che usano i file (non le importazioni dalla ksoap2.jar)
  4. Usa risposta rallat (copio-incollato):

    • ServiceConnectionSE.java aggiungere questo per accettare certificato non attendibile:

      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) { 
           } 
          } 
      }; 
      
    • quindi utilizzare questo costruttori per consentire certificati non attendibili e non nomi host verificati:

      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()); 
      }  
      
    • Seconda 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. Nel codice basta usare:

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

Altre cose come nel tutorial

+1

@Zirael ... Grazie per il vostro aiuto è stato utile ... ero ansioso di sapere piuttosto che lavorare in giro se avessi il certificato di sicurezza ... come posso procedere ulteriormente con esso ..? –

+0

Impossibile trovare i sorgenti di ksoap usando il link fornito - è rotto. = \ aggiornamento: ho trovato ... basta usare: https: //github.com/mosabua/ksoap2-android/ – micyunu

4

trovo la risposta da solo

  • su ServiceConnectionSE.java aggiungere questo per accettare il certificato non attendibile:

    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) { 
         } 
        } 
    }; 
    
  • poi nel costruttore aggiungere questo per consentire non attendibile certificati e nomi host non verificati:

    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()); 
    
3

creare una nuova classe FakeX509TrustManager per gestire il problema del certificato,

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

La nuova classe creata è come il seguente:

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()); 
    } 

} 
+0

Serious +1 jowett ... Ho messo il tuo codice alla fine della mia attività e tutto quello che avevo fare è stato rendere il FakeX509TrustManager statico e ha ottenuto tutto ... Ho letto più di alcuni post SO e questo è stato il più facile da implementare di gran lunga. Notare le date delle risposte precedenti in questo post ... abbastanza detto. Avete qualche risorsa sul modo più semplice per NON fidarsi di tutti i certificati per il codice di produzione? – whyoz

+0

@whyoz scusa, nessuna risorsa. – jowett

11

Controllo di nuovo questo problema, ho scoperto una soluzione più pulita per me. Non è necessaria alcuna modifica dei file KSOAP2.

Nel progetto, collegare ksoap2-android-assembly-3.0.0-jar, senza modifiche.

successivo, creare un file denominato SSLConnection.java con questo codice:

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()); 
     } 
    } 
} 

E basta chiamare al SSLConection.allowAllSSL(); prima di chiamare un metodo server tramite KSOAP2. È tutto, funziona per me. Tutti i certificati SSL sono accettati e posso usare KSOAP2 con il protocollo https.

+0

Grazie per aver aggiunto anche il tuo snippet – rallat

+0

Soluzione semplice e perfetta! Grazie :) – OmarBizreh

+0

felice di aiutare! :-) – Neonigma