httptransportse - ksoap2 android studio example
KSOAP 2 Android con HTTPS (4)
Encuentro la respuesta por mi cuenta
en ServiceConnectionSE.java, agregue esto para aceptar el certificado no confiable:
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) { } } };
luego, en el constructor, agregue esto para permitir certificados no confiables 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());
Estoy usando KSOAP2 para administrar SOAP en Android pero usa https para la URL de SOAP y recibo 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 empresa y no tengo acceso para cambiarlo.
Gracias
No puedo comentar todavía así que publico mis comentarios para responder aquí. Su solución funciona, pero necesita más explicaciones. Para ejecutar ksoap2 con ssl:
- Coloque
ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar
en un proyecto - Descargue las fuentes de ksoap2 de https://github.com/mosabua/ksoap2-android/tree/ (repositorio de ksoap2)
- Copie
HttpTransportSE.java
,ServiceConnectionSE.java
(también necesitaba copiarTransport.java
,ServiceConnection.java
yHeaderProperty.java
). Elimine las importaciones de esos archivos y asegúrese de que usen sus archivos (no las importaciones desdeksoap2.jar
) Utilice la respuesta rallat (la copié y pegué):
ServiceConnectionSE.java
agregue esto para aceptar el certificado no confiable: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) { } } };
luego use estos constructores para permitir certificados no confiables y nombres de host no verificados:
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()); }
Segundo 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); }
En tu código simplemente usa:
HttpTransportSE aht = new HttpTransportSE(URL); aht.call(SOAP_ACTION, envelope);
Otras cosas como en tutoriales
Cree una nueva clase FakeX509TrustManager para manejar el problema del certificado,
FakeX509TrustManager.allowAllSSL();
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
La nueva clase creada es 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());
}
}
Comprobando nuevamente este problema, descubrí una solución más limpia para mí. No es necesario modificar los archivos KSOAP2.
En su proyecto, vincule 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 solo llame a SSLConection.allowAllSSL();
antes de llamar a un método de servidor a través de KSOAP2. Es todo, funciona para mí. Se aceptan todos los certificados SSL y puedo usar KSOAP2 con protocolo https.