Solicitud HTTP de SSL de Android mediante cert auto-firmado y CA

Tengo una aplicación de Android que se está conectando a un servicio web SSL que alojamos. El servidor Web es apache y tiene su propia CA que creamos y un certificado SSL auto-firmado.

He importado nuestro certificado de CA en la tableta de Android en la sección de certificados de confianza de usuario en Seguridad.

He probado el acceso al servidor web y puedo confirmar que el certificado del servicio web se muestra como válido (captura de pantalla a continuación)

Certificado válido

Aquí está el certificado en la configuración de seguridad:

Certificado de confianza

Ahora, cuando intento acceder al servicio web en mi aplicación, obtengo la excepción "No Peer Certificate" que se dispara.

Esta es la implementación SSL simplificada:

public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // allows network on main thread (temp hack) StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); SchemeRegistry schemeRegistry = new SchemeRegistry(); //schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); schemeRegistry.register(new Scheme("https", newSSLSocketFactory(), 443)); HttpParams params = new BasicHttpParams(); SingleClientConnManager mgr = new SingleClientConnManager(params, schemeRegistry); HttpClient client = new DefaultHttpClient(mgr, params); HttpPost httpRequest = new HttpPost("https://our-web-service.com"); try { client.execute(httpRequest); } catch (Exception e) { e.printStackTrace(); // } } /* * Standard SSL CA Store Setup // */ private SSLSocketFactory newSSLSocketFactory() { KeyStore trusted; try { trusted = KeyStore.getInstance("AndroidCAStore"); trusted.load(null, null); Enumeration<String> aliases = trusted.aliases(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); X509Certificate cert = (X509Certificate) trusted.getCertificate(alias); Log.d("", "Alias="+alias); Log.d("", "Subject DN: " + cert.getSubjectDN().getName()); Log.d("", "Issuer DN: " + cert.getIssuerDN().getName()); } SSLSocketFactory sf = new SSLSocketFactory(trusted); sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); return sf; } catch (Exception e) { // TODO Auto-generated catch block throw new AssertionError(e); } } } 

El bucle while sólo escupe los certificados y puedo ver mi propia CA en los registros. Pero aún así obtengo la excepción "No Peer Certificate".

10-17 18: 29: 01.234: I / System.out (4006): Ningún certificado de compañero

¿Tengo que cargar manualmente mi certificado de CA de alguna manera en esta implementación?

Resuelto mediante: HttpsURLConnection

 URLConnection conn = null; URL url = new URL(strURL); conn = url.openConnection(); HttpsURLConnection httpsConn = (HttpsURLConnection) conn; 

Esto parece funcionar bien con los certificados de CA instalados por el usuario.

Puede realizar la tarea también utilizando DefaultHttpClient , aunque aquí se sugiere :

Preferir HttpURLConnection para el nuevo código

Preste atención también en la importación o adición de certificados a su aplicación, ya que puede tener problemas al actualizar el certificado cuando expire.

Aquí cómo obtener un DefaultHttpClient confiando en un certificado autofirmado:

  * This method returns the appropriate HttpClient. * @param isTLS Whether Transport Layer Security is required. * @param trustStoreInputStream The InputStream generated from the BKS keystore. * @param trustStorePsw The password related to the keystore. * @return The DefaultHttpClient object used to invoke execute(request) method. private DefaultHttpClient getHttpClient(boolean isTLS, InputStream trustStoreInputStream, String trustStorePsw) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, UnrecoverableKeyException { DefaultHttpClient client = null; SchemeRegistry schemeRegistry = new SchemeRegistry(); Scheme http = new Scheme("http", PlainSocketFactory.getSocketFactory(), 8080); schemeRegistry.register(http); if(isTLS) { KeyStore trustKeyStore = null; char[] trustStorePswCharArray = null; if(trustStorePsw!=null) { trustStorePswCharArray = trustStorePsw.toCharArray(); } trustKeyStore = KeyStore.getInstance("BKS"); trustKeyStore.load(trustStoreInputStream, trustStorePswCharArray); SSLSocketFactory sslSocketFactory = null; sslSocketFactory = new SSLSocketFactory(trustKeyStore); Scheme https = new Scheme("https", sslSocketFactory, 8443); schemeRegistry.register(https); } HttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, CONNECTION_TIMEOUT); HttpConnectionParams.setSoTimeout(httpParams, SOCKET_TIMEOUT); ClientConnectionManager clientConnectionManager = new ThreadSafeClientConnManager(httpParams, schemeRegistry); client = new DefaultHttpClient(clientConnectionManager, httpParams); return client; } 

Y aquí cómo obtener una HttpsURLConnection :

  * This method set the certificate for the HttpsURLConnection * @param url The url to contact. * @param certificateInputStream The InputStream generated from the .crt certificate. * @param certAlias The alias for the certificate. * @return The returned HttpsURLConnection private HttpsURLConnection getHttpsURLConnection(URL url, InputStream certificateInputStream, String certAlias) throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException { HttpsURLConnection connection = null; CertificateFactory certFactory = null; Certificate cert = null; KeyStore keyStore = null; TrustManagerFactory tmFactory = null; SSLContext sslContext = null; // Load certificates from an InputStream certFactory = CertificateFactory.getInstance("X.509"); cert = certFactory.generateCertificate(certificateInputStream); certificateInputStream.close(); // Create a KeyStore containing the trusted certificates keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); keyStore.setCertificateEntry(certAlias, cert); // Create a TrustManager that trusts the certificates in our KeyStore tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmFactory.init(keyStore); // Create an SSLContext that uses our TrustManager sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmFactory.getTrustManagers(), null); connection = (HttpsURLConnection)url.openConnection(); connection.setSSLSocketFactory(sslContext.getSocketFactory()); return connection; } 
  • Android 2.3.x javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Ancla de confianza para la ruta de certificación no encontrada
  • Error SSL de Android: certificado no de confianza ... a veces
  • Javax.net.ssl.SSLException: Error de lectura: ssl = 0x9524b800: Error de E / S durante la llamada al sistema, Conexión restablecida por pares
  • Uso de la versión personalizada de la aplicación de App Engine en Android
  • Ssl en android tema extraño
  • Pinzado de certificado SSL con Picasso
  • ¿Cómo hacer un HTTPS POST de Android?
  • Comunicación de servicio web Https de Android (SSL / TLS 1.2)
  • Cómo resolver 'no puede encontrar una ruta de certificación válida a la meta solicitada' en Android Studio 2.3.2
  • Cómo importar certificado SSL autofirmado a Volley en Android 4.1+
  • Aceptar certificados SSL autofirmados-> donde configurar TrustManager predeterminado
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.