2010-08-09 22 views
12

Estoy usando KSOAP2 para administrar SOAP en Android pero usa https para la url SOAP y obtengo este error: javax.net.ssl.SSLException: Certificado de servidor no confiable
Un error normal porque el certificado no es de confianza, pero ¿alguien sabe cómo solucionar este error? No puedo administrar el certificado porque es de otra compañía y no tengo acceso para cambiarlo.KSOAP 2 Android con HTTPS

Gracias

Respuesta

10

No puedo comentar todavía así que postearé mis comentarios a rallat answer aquí. Su solución funciona, pero necesita más explicaciones. Para ejecutar ksoap2 con SSL:

  1. Deja ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar en un proyecto
  2. fuentes de descarga de ksoap2 https://github.com/mosabua/ksoap2-android/tree/ (repositorio ksoap2)
  3. Copia HttpTransportSE.java, ServiceConnectionSE.java (también necesario para copiar Transport.java, ServiceConnection.java y HeaderProperty.java).Eliminar las importaciones de esos archivos y asegúrese de que utilizan sus archivos (no las importaciones de ksoap2.jar)
  4. Uso rallat respuesta (copio-pegó):

    • ServiceConnectionSE.java añadir esto para aceptar el certificado no es de confianza:

      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) { 
           } 
          } 
      }; 
      
    • continuación, utilizar este constructores para permiten certificados no son de confianza y no nombres de host verificadas:

      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()); 
      }  
      
    • Segunda 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. En su código sólo tiene que utilizar:

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

Otras cosas como en tutoriales

+1

@Zirael ... Gracias por su ayuda, me ayudó ... Estaba ansioso por saber en lugar de trabajar si tuviera el certificado de seguridad ... ¿Cómo puedo continuar con esto ...? –

+0

No se pueden encontrar las fuentes de ksoap utilizando el enlace proporcionado; está roto. = \ actualización: Lo encontré ... solo uso: https: //github.com/mosabua/ksoap2-android/ – micyunu

4

que encontrar la respuesta por mí mismo

  • en ServiceConnectionSE.java agregar este certificado no es de confianza para aceptar:

    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) { 
         } 
        } 
    }; 
    
  • continuación, en el constructor añadir esto para permitir que no se confía certificados y nombres de host no verificados:

    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

crear una nueva clase FakeX509TrustManager para manejar el problema de certificado,

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

La nueva clase creada es como la siguiente:

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

Serio +1 jowett ... Puse tu código al final de mi actividad y todo lo que tenía hacer era hacer FakeX509TrustManager estático y pasó de largo ... He leído más de unas pocas publicaciones SO y esta fue la más fácil de implementar con diferencia. Observe las fechas en las respuestas anteriores en esta publicación ... suficientemente dicho. ¿Tiene algún recurso de la manera más fácil para NO confiar en todos los certs para el código de producción? – whyoz

+0

@whyoz lo siento, no hay recurso. – jowett

11

Comprobación de nuevo este problema, he descubierto una solución más limpia para mí. No es necesario modificar los archivos KSOAP2.

En su proyecto, vincule el ksoap2-android-assembly-3.0.0-jar, sin modificaciones.

A continuación, cree un archivo llamado SSLConnection.java con este código:

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

Y simplemente llame a SSLConection.allowAllSSL(); antes de llamar a un método servidor a través de KSOAP2. Es todo, funciona para mí. Se aceptan todos los certificados SSL y puedo usar KSOAP2 con protocolo https.

+0

Gracias por agregar su fragmento también – rallat

+0

¡Solución perfecta y simple! Gracias :) – OmarBizreh

+0

encantados de ayudar! :-) – Neonigma