Confiar en todos los certificados utilizando HttpClient sobre HTTPS

393

Recientemente publiqué una pregunta sobre el HttpClientHttps (que se encuentra aquí ). He avanzado un poco, pero me he encontrado con nuevos problemas. Al igual que con mi último problema, parece que no puedo encontrar un ejemplo en ningún lugar que me funcione. Básicamente, quiero que mi cliente acepte cualquier certificado (porque solo estoy apuntando a un servidor) pero sigo obteniendo unjavax.net.ssl.SSLException: Not trusted server certificate exception.

Entonces esto es lo que tengo:


    public void connect() throws A_WHOLE_BUNCH_OF_EXCEPTIONS {

        HttpPost post = new HttpPost(new URI(PROD_URL));
        post.setEntity(new StringEntity(BODY));

        KeyStore trusted = KeyStore.getInstance("BKS");
        trusted.load(null, "".toCharArray());
        SSLSocketFactory sslf = new SSLSocketFactory(trusted);
        sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme ("https", sslf, 443));
        SingleClientConnManager cm = new SingleClientConnManager(post.getParams(),
                schemeRegistry);

        HttpClient client = new DefaultHttpClient(cm, post.getParams());
        HttpResponse result = client.execute(post);
    }

Y aquí está el error que obtengo:

    W/System.err(  901): javax.net.ssl.SSLException: Not trusted server certificate 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:360) 
    W/System.err(  901):    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:321) 
    W/System.err(  901):    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:129) 
    W/System.err(  901):    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
    W/System.err(  901):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
    W/System.err(  901):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:129) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.access$0(MainActivity.java:77) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity$2.run(MainActivity.java:49) 
    W/System.err(  901): Caused by: java.security.cert.CertificateException: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:157) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:355) 
    W/System.err(  901):    ... 12 more 
    W/System.err(  901): Caused by: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty 
    W/System.err(  901):    at java.security.cert.PKIXParameters.checkTrustAnchors(PKIXParameters.java:645) 
    W/System.err(  901):    at java.security.cert.PKIXParameters.<init>(PKIXParameters.java:89) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.<init>(TrustManagerImpl.java:89) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl.engineGetTrustManagers(TrustManagerFactoryImpl.java:134) 
    W/System.err(  901):    at javax.net.ssl.TrustManagerFactory.getTrustManagers(TrustManagerFactory.java:226)W/System.err(  901):     at org.apache.http.conn.ssl.SSLSocketFactory.createTrustManagers(SSLSocketFactory.java:263) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:190) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:216) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:107) 
    W/System.err(  901):    ... 2 more
harrisonlee
fuente
17
Necesitaba hacer esto para uso interno. Realmente espero que no permitas que los usuarios externos a tu empresa usen tu aplicación, ya que la has abierto a un hombre en el medio del ataque y luego serían vulnerables a que alguien secuestrara su sesión. sin embargo, necesito hacer esto temporalmente para algunas pruebas hasta que tenga el certificado real en la mano ... espero que lo esté haciendo por el mismo tipo de razón temporal o la aplicación solo se usa internamente.
Dean Hiller
Probé estas soluciones en 4.3 apache http client, pero en su mayoría están en desuso. Aquí no hay una solución desaprobada: stackoverflow.com/a/18941950/2039471
Alexander Chzhen
Java 1.6 no tiene soporte SNI, lo que también es problemático en estos escenarios: si no construye la solicitud correctamente, podría obtener un certificado que no coincida con la solicitud. Ver cuestiones.apache.org/jira/browse/HTTPCLIENT-1119
Bron Davies
2
Esta pregunta se cita en el artículo El código más peligroso del mundo como un ejemplo de razonamiento falaz. (trabajo de investigación: cs.utexas.edu/~shmat/shmat_ccs12.pdf )
mk_

Respuestas:

421

Nota: No implemente esto en el código de producción que usará en una red en la que no confía por completo. Especialmente todo lo que pasa por internet público.

Tu pregunta es justo lo que quiero saber. Después de hacer algunas búsquedas, la conclusión es la siguiente.

En la forma HttpClient, debe crear una clase personalizada desde org.apache.http.conn.ssl.SSLSocketFactory, no la org.apache.http.conn.ssl.SSLSocketFactory en sí. Se pueden encontrar algunas pistas en esta publicación El manejo personalizado de SSL dejó de funcionar en Android 2.2 FroYo .

Un ejemplo es como ...

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.conn.ssl.SSLSocketFactory;
public class MySSLSocketFactory extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");

    public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(truststore);

        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

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

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

        sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}

y use esta clase mientras crea una instancia de HttpClient.

public HttpClient getNewHttpClient() {
    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);

        MySSLSocketFactory sf = new MySSLSocketFactory(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}

Por cierto, el siguiente enlace es para alguien que está buscando la solución HttpURLConnection. Https Connection Android

He probado los dos tipos de soluciones anteriores en froyo, y todos funcionan de maravilla en mis casos. Finalmente, usar HttpURLConnection puede enfrentar los problemas de redireccionamiento, pero esto va más allá del tema.

Nota: Antes de decidirse a confiar en todos los certificados, probablemente debería conocer bien el sitio y no será perjudicial para el usuario final.

De hecho, el riesgo que corres debe considerarse con cuidado, incluido el efecto del sitio simulado del hacker mencionado en los siguientes comentarios que aprecio profundamente. En alguna situación, aunque puede ser difícil cuidar todos los certificados, es mejor que conozca los inconvenientes implícitos para confiar en todos ellos.

Daniel
fuente
150
esta respuesta probablemente se debe tener en cuenta que confiar en todos los certificados es terriblemente inseguro y anula todo el propósito de ssl ...
yanokwa
22
@sweeney: excepto que no está garantizado que estés hablando con el servidor que crees que eres. Si alguien ha estropeado un servidor DNS, podría estar comunicando una clave de cifrado con el servidor de un hacker.
Richard Szalay
12
@sweeney En otras palabras, ahora estás sujeto a ataques de hombre en el medio. También debe tener en cuenta que ese código no cumple con las especificaciones: consulte el Javadoc. getAcceptedIssuers()no está permitido devolver nulo.
Marqués de Lorne
25
-1 Porque es una idea terrible aceptar todos los certificados. Es una pena que haya tantos blogs y tutoriales que felizmente guíen a los desarrolladores de Java por el camino de hacer lo incorrecto.
Tim Bender
57
+1 Porque necesitaba una solución rápida solo para fines de depuración. No usaría esto en producción debido a las preocupaciones de seguridad que otros han mencionado, pero esto era exactamente lo que necesitaba para las pruebas. ¡Gracias!
Baile el
495

Básicamente, tiene cuatro posibles soluciones para solucionar una excepción "No confiable" en Android usando httpclient:

  1. Confía en todos los certificados. No hagas esto, a menos que realmente sepas lo que estás haciendo.
  2. Cree un SSLSocketFactory personalizado que confíe solo en su certificado. Esto funciona siempre que sepa exactamente a qué servidores se va a conectar, pero tan pronto como necesite conectarse a un nuevo servidor con un certificado SSL diferente, deberá actualizar su aplicación.
  3. Cree un archivo de almacén de claves que contenga la "lista maestra" de certificados de Android, luego agregue el suyo. Si alguno de esos certificados caduca en el futuro, usted es responsable de actualizarlos en su aplicación. No puedo pensar en una razón para hacer esto.
  4. Cree un SSLSocketFactory personalizado que use el certificado KeyStore incorporado, pero recurra a un KeyStore alternativo para cualquier cosa que no se verifique con el valor predeterminado.

Esta respuesta utiliza la solución n. ° 4, que me parece la más sólida.

La solución es utilizar un SSLSocketFactory que puede aceptar múltiples KeyStores, lo que le permite suministrar su propio KeyStore con sus propios certificados. Esto le permite cargar certificados adicionales de nivel superior como Thawte que pueden faltar en algunos dispositivos Android. También le permite cargar sus propios certificados autofirmados también. Primero utilizará los certificados de dispositivo predeterminados integrados y recurrirá a sus certificados adicionales solo cuando sea necesario.

Primero, querrás determinar qué certificado te falta en tu KeyStore. Ejecute el siguiente comando:

openssl s_client -connect www.yourserver.com:443

Y verá resultados como el siguiente:

Certificate chain
 0 s:/O=www.yourserver.com/OU=Go to 
   https://www.thawte.com/repository/index.html/OU=Thawte SSL123 
   certificate/OU=Domain Validated/CN=www.yourserver.com
   i:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV SSL CA
 1 s:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV SSL CA
   i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 
   2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA

Como puede ver, nuestro certificado raíz es de Thawte. Vaya al sitio web de su proveedor y busque el certificado correspondiente. Para nosotros, fue aquí , y se puede ver que el que necesitábamos era el Copyright 2006.

Si está utilizando un certificado autofirmado, no es necesario que realice el paso anterior ya que ya tiene su certificado de firma.

Luego, cree un archivo de almacén de claves que contenga el certificado de firma faltante. Crazybob tiene detalles sobre cómo hacer esto en Android , pero la idea es hacer lo siguiente:

Si aún no lo tiene, descargue la biblioteca del proveedor del castillo hinchable de: http://www.bouncycastle.org/latest_releases.html . Esto irá en tu classpath a continuación.

Ejecute un comando para extraer el certificado del servidor y crear un archivo pem. En este caso, mycert.pem.

echo | openssl s_client -connect ${MY_SERVER}:443 2>&1 | \
 sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > mycert.pem

Luego ejecute los siguientes comandos para crear el almacén de claves.

export CLASSPATH=/path/to/bouncycastle/bcprov-jdk15on-155.jar
CERTSTORE=res/raw/mystore.bks
if [ -a $CERTSTORE ]; then
    rm $CERTSTORE || exit 1
fi
keytool \
      -import \
      -v \
      -trustcacerts \
      -alias 0 \
      -file <(openssl x509 -in mycert.pem) \
      -keystore $CERTSTORE \
      -storetype BKS \
      -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
      -providerpath /path/to/bouncycastle/bcprov-jdk15on-155.jar \
      -storepass some-password

Notarás que el script anterior coloca el resultado en res/raw/mystore.bks. Ahora tiene un archivo que cargará en su aplicación de Android que proporciona los certificados faltantes.

Para hacer esto, registre su SSLSocketFactory para el esquema SSL:

final SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", createAdditionalCertsSSLSocketFactory(), 443));

// and then however you create your connection manager, I use ThreadSafeClientConnManager
final HttpParams params = new BasicHttpParams();
...
final ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params,schemeRegistry);

Para crear su SSLSocketFactory:

protected org.apache.http.conn.ssl.SSLSocketFactory createAdditionalCertsSSLSocketFactory() {
    try {
        final KeyStore ks = KeyStore.getInstance("BKS");

        // the bks file we generated above
        final InputStream in = context.getResources().openRawResource( R.raw.mystore);  
        try {
            // don't forget to put the password used above in strings.xml/mystore_password
            ks.load(in, context.getString( R.string.mystore_password ).toCharArray());
        } finally {
            in.close();
        }

        return new AdditionalKeyStoresSSLSocketFactory(ks);

    } catch( Exception e ) {
        throw new RuntimeException(e);
    }
}

Y finalmente, el código AdditionalKeyStoresSSLSocketFactory, que acepta su nuevo KeyStore y comprueba si el KeyStore incorporado no puede validar un certificado SSL:

/**
 * Allows you to trust certificates from additional KeyStores in addition to
 * the default KeyStore
 */
public class AdditionalKeyStoresSSLSocketFactory extends SSLSocketFactory {
    protected SSLContext sslContext = SSLContext.getInstance("TLS");

    public AdditionalKeyStoresSSLSocketFactory(KeyStore keyStore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(null, null, null, null, null, null);
        sslContext.init(null, new TrustManager[]{new AdditionalKeyStoresTrustManager(keyStore)}, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }



    /**
     * Based on http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#X509TrustManager
     */
    public static class AdditionalKeyStoresTrustManager implements X509TrustManager {

        protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();


        protected AdditionalKeyStoresTrustManager(KeyStore... additionalkeyStores) {
            final ArrayList<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>();

            try {
                // The default Trustmanager with default keystore
                final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                original.init((KeyStore) null);
                factories.add(original);

                for( KeyStore keyStore : additionalkeyStores ) {
                    final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                    additionalCerts.init(keyStore);
                    factories.add(additionalCerts);
                }

            } catch (Exception e) {
                throw new RuntimeException(e);
            }



            /*
             * Iterate over the returned trustmanagers, and hold on
             * to any that are X509TrustManagers
             */
            for (TrustManagerFactory tmf : factories)
                for( TrustManager tm : tmf.getTrustManagers() )
                    if (tm instanceof X509TrustManager)
                        x509TrustManagers.add( (X509TrustManager)tm );


            if( x509TrustManagers.size()==0 )
                throw new RuntimeException("Couldn't find any X509TrustManagers");

        }

        /*
         * Delegate to the default trust manager.
         */
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0);
            defaultX509TrustManager.checkClientTrusted(chain, authType);
        }

        /*
         * Loop over the trustmanagers until we find one that accepts our server
         */
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            for( X509TrustManager tm : x509TrustManagers ) {
                try {
                    tm.checkServerTrusted(chain,authType);
                    return;
                } catch( CertificateException e ) {
                    // ignore
                }
            }
            throw new CertificateException();
        }

        public X509Certificate[] getAcceptedIssuers() {
            final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
            for( X509TrustManager tm : x509TrustManagers )
                list.addAll(Arrays.asList(tm.getAcceptedIssuers()));
            return list.toArray(new X509Certificate[list.size()]);
        }
    }

}
emmby
fuente
Hola @emmby, esta parece ser la respuesta perfecta para mi problema, pero sigo sin tener conexión SSL. ¿Puedes echarle un vistazo? http://stackoverflow.com/questions/7822381/need-help-understanding-certificate-chains
Matthias B
Gracias por la gran crítica @emmby! A veces recibo un retraso muy largo y luego una excepción javax.net.ssl.SSLException: Read error :. ¿Alguna idea? ¿Cómo puedo establecer un tiempo de espera si la solución es la misma que stackoverflow.com/questions/5909308/android-2-3-4-ssl-problem ?
Edwin Evans el
3
@emmby, ¿podría decir dónde debo poner este código export CLASSPATH = bcprov-jdk16-145.jar CERTSTORE = res / raw / mystore.bks if [-a $ CERTSTORE]; entonces rm $ CERTSTORE || salida 1 fi keytool \ -import \ -v \ -trustcacerts \ -alias 0 \ -file <(openssl x509 -in mycert.pem) \ -keystore $ CERTSTORE \ -storetype BKS \ -provider org.bouncycastle.jce.provider. BouncyCastleProvider \ -providerpath /usr/share/java/bcprov.jar \ -storepass some-password
Rikki Tikki Tavi
1
Hola @emmby. Estoy usando su solución en mi aplicación y estoy usando un certificado autofirmado de mi servidor, pero obtengo una CertificateException () en el método checkServerTrusted () . Intenté comentar esa excepción de lanzamiento, y funciona. si no valida mi certificado de servidor, ¿puedo manejarlo de otra manera? ¿Puede guiarme cuál es la mejor solución en este caso?
Ankit
77
Esto debe ser marcado como la respuesta correcta. Una de las respuestas más completas y bien escritas que he visto en SO. Dope
Kachi
74

Agregue este código antes del HttpsURLConnectiony se hará. Lo tengo.

private void trustEveryone() { 
    try { 
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){ 
                    public boolean verify(String hostname, SSLSession session) { 
                            return true; 
                    }}); 
            SSLContext context = SSLContext.getInstance("TLS"); 
            context.init(null, new X509TrustManager[]{new X509TrustManager(){ 
                    public void checkClientTrusted(X509Certificate[] chain, 
                                    String authType) throws CertificateException {} 
                    public void checkServerTrusted(X509Certificate[] chain, 
                                    String authType) throws CertificateException {} 
                    public X509Certificate[] getAcceptedIssuers() { 
                            return new X509Certificate[0]; 
                    }}}, new SecureRandom()); 
            HttpsURLConnection.setDefaultSSLSocketFactory( 
                            context.getSocketFactory()); 
    } catch (Exception e) { // should never happen 
            e.printStackTrace(); 
    } 
} 

Espero que esto te ayude.

Alok Gupta
fuente
22
Vea los comentarios anteriores bajo la respuesta aceptada. Esta 'solución' es radicalmente insegura.
Marqués de Lorne
55
Esta es la solución ideal de preguntas y respuestas. Corto y "simplemente funciona".
Steve Smith
55
¡Respuesta perfecta para fines de prueba! Y sí, es una mala idea usarlo en producción, pero vamos ... eso debería estar claro para todos los que miran el título de la pregunta. ¡Sigue respondiendo mejor / más corto / con el mismo nivel de seguridad!
Levite
34

Esta es una mala idea. Confiar en cualquier certificado es solo (muy) ligeramente mejor que no usar SSL en absoluto. Cuando dice "Quiero que mi cliente acepte cualquier certificado (porque solo estoy señalando a un servidor)" está asumiendo que esto significa que de alguna manera señalar a "un servidor" es seguro, lo cual no está en una red pública.

Estás completamente abierto a un ataque de hombre en el medio al confiar en cualquier certificado. Cualquier persona puede usar su conexión proxy mediante el establecimiento de una conexión SSL separada con usted y con el servidor final. El MITM tiene acceso a toda su solicitud y respuesta. A menos que realmente no necesite SSL en primer lugar (su mensaje no tiene nada sensible y no hace autenticación), no debe confiar en todos los certificados a ciegas.

Debería considerar agregar el certificado público a un jks usando keytool y usarlo para construir su fábrica de sockets, como este:

    KeyStore ks = KeyStore.getInstance("JKS");

    // get user password and file input stream
    char[] password = ("mykspassword")).toCharArray();
    ClassLoader cl = this.getClass().getClassLoader();
    InputStream stream = cl.getResourceAsStream("myjks.jks");
    ks.load(stream, password);
    stream.close();

    SSLContext sc = SSLContext.getInstance("TLS");
    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

    kmf.init(ks, password);
    tmf.init(ks);

    sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);

    return sc.getSocketFactory();

Esto tiene una advertencia a tener en cuenta. El certificado caducará eventualmente y el código dejará de funcionar en ese momento. Puede determinar fácilmente cuándo ocurrirá esto mirando el certificado.

Dan
fuente
55
Si no está utilizando la autenticación de certificado de cliente, desde el lado del cliente, no necesita un administrador de claves (uso nullen SSLContext.init). You should also use the default algorithms (KMF/TMF.getDefaultAlgorithm() ), instead of hard-coding SunX509` (más aún porque el valor predeterminado para TMF está realmente PKIXen Sun / Oracle JVM).
Bruno
¿Existe un archivo de certificados raíz listo para usar? (como lo hacen los navegadores)
dani herrera
¿De dónde myjks.jksviene?
zionpi
1
@zionpi Generado usando Java "keytool".
Dan
22

Puede deshabilitar la verificación HttpURLConnection SSL para fines de prueba de esta manera desde la API 8:

    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    if (conn instanceof HttpsURLConnection) {
        HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
        httpsConn.setSSLSocketFactory(SSLCertificateSocketFactory.getInsecure(0, null));
        httpsConn.setHostnameVerifier(new AllowAllHostnameVerifier());
    }
hfmanson
fuente
2
org.apache.http.conn.ssl.AllowAllHostnameVerifieres obsoleto.
zackygaurav
2
@zackygaurav Según el javadoc , AllowAllHostnameVerifierse reemplaza por NoopHostnameVerifier"
DLight
10

La API de HttpComponents ha cambiado. Funciona con el siguiente código.

public static HttpClient getTestHttpClient() {
    try {
        SSLSocketFactory sf = new SSLSocketFactory(new TrustStrategy(){
            @Override
            public boolean isTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
                return true;
            }
        }, new AllowAllHostnameVerifier());

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("https",8444, sf));
        ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry);
        return new DefaultHttpClient(ccm);
    } catch (Exception e) {
        e.printStackTrace();
        return new DefaultHttpClient();
    }
}
Prabhu Periasamy
fuente
Usar una estrategia de confianza personalizada es la respuesta correcta. Gracias.
Matt Friedman
10

El código anterior en https://stackoverflow.com/a/6378872/1553004 es correcto, excepto que también DEBE llamar al verificador de nombre de host:

    @Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
    SSLSocket sslSocket = (SSLSocket)sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    getHostnameVerifier().verify(host, sslSocket);
    return sslSocket;
}

Me inscribí en stackoverflow expresamente para agregar esta solución. ¡Presta atención a mi advertencia!

Robert Blair
fuente
Una vez que verifique el certificado de esta manera en la primera conexión, ¿qué hace con las conexiones posteriores? ¿Aprovechas el conocimiento que obtuviste de la primera conexión? ¿Qué sucede si se utiliza un certificado falso con el mismo nombre en el intento de conexión 3?
jww
6

Estoy agregando una respuesta para aquellos que usan httpclient-4.5, y probablemente también funcione para 4.4.

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.fluent.ContentResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;



public class HttpClientUtils{

public static HttpClient getHttpClientWithoutSslValidation_UsingHttpClient_4_5_2() {
    try {
        SSLContextBuilder builder = new SSLContextBuilder();
        builder.loadTrustMaterial(null, new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        });
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), new NoopHostnameVerifier());
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); 
        return httpclient;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
}
raisercostin
fuente
¿Qué es la nueva clase NoopHostnameVerifier ()?
Mushtakim Ahmed Ansari
1
@MushtakimAhmedAnsari De los documentos: "El NO_OP HostnameVerifier esencialmente desactiva la verificación del nombre de host. Esta implementación no es operativa y nunca arroja la SSLException".
raisercostin
Gracias por la gran respuesta. Esta debería obtener más votos.
Abhay Dwivedi
¿Como lo uso? o está sugiriendo que simplemente tener la clase anulará las verificaciones de los certificados SSL?
Behelit
si. que httpClient cuando se usa no validará los certificados https
raisercostin
4

Confiar en todos los certificados no era una alternativa real para mí, así que hice lo siguiente para que HttpsURLConnection confiara en un nuevo certificado (consulte también http://nelenkov.blogspot.jp/2011/12/using-custom-certificate-trust-store- on.html ).

  1. Obtener el certificado; Logré esto exportando el certificado en Firefox (haga clic en el pequeño ícono de candado, obtenga los detalles del certificado, haga clic en exportar), luego usé portecle para exportar un almacén de confianza (BKS).

  2. Cargue el Truststore de /res/raw/geotrust_cert.bks con el siguiente código:

        final KeyStore trustStore = KeyStore.getInstance("BKS");
        final InputStream in = context.getResources().openRawResource(
                R.raw.geotrust_cert);
        trustStore.load(in, null);
    
        final TrustManagerFactory tmf = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);
    
        final SSLContext sslCtx = SSLContext.getInstance("TLS");
        sslCtx.init(null, tmf.getTrustManagers(),
                new java.security.SecureRandom());
    
        HttpsURLConnection.setDefaultSSLSocketFactory(sslCtx
                .getSocketFactory());
koljaTM
fuente
Me sale este error. IOExceptionjavax.net.ssl.SSLPeerUnverifiedException: No peer certificate. Esto cuando se realiza la llamada de ejecución real en el HttpClient después de que se realiza la configuración anterior.
Michael
3

Aquí hay una versión mucho más simple que usa el código de cliente http 4.1.2. Esto se puede modificar a cualquier algoritmo de confianza que considere adecuado.

public static HttpClient getTestHttpClient() {
    try {
        SSLSocketFactory sf = new SSLSocketFactory(new TrustStrategy(){
            @Override
            public boolean isTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
                return true;
            }
        });
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("https", 443, sf));
        ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry);
        return new DefaultHttpClient(ccm);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}
Joseph Valerio
fuente
3

Recibí una respuesta de "emmby" (respondió el 16 de junio de 11 a las 21:29), elemento n. ° 4: "Cree un SSLSocketFactory personalizado que use el certificado integrado KeyStore, pero recurra a un KeyStore alternativo para cualquier cosa que falle para verificar con el valor predeterminado ".

Esta es una implementación simplificada. Cargue el almacén de claves del sistema y fusione con el almacén de claves de la aplicación.

public HttpClient getNewHttpClient() {
    try {
        InputStream in = null;
        // Load default system keystore
        KeyStore trusted = KeyStore.getInstance(KeyStore.getDefaultType()); 
        try {
            in = new BufferedInputStream(new FileInputStream(System.getProperty("javax.net.ssl.trustStore"))); // Normally: "/system/etc/security/cacerts.bks"
            trusted.load(in, null); // no password is "changeit"
        } finally {
            if (in != null) {
                in.close();
                in = null;
            }
        }

        // Load application keystore & merge with system
        try {
            KeyStore appTrusted = KeyStore.getInstance("BKS"); 
            in = context.getResources().openRawResource(R.raw.mykeystore);
            appTrusted.load(in, null); // no password is "changeit"
            for (Enumeration<String> e = appTrusted.aliases(); e.hasMoreElements();) {
                final String alias = e.nextElement();
                final KeyStore.Entry entry = appTrusted.getEntry(alias, null);
                trusted.setEntry(System.currentTimeMillis() + ":" + alias, entry, null);
            }
        } finally {
            if (in != null) {
                in.close();
                in = null;
            }
        }

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

        SSLSocketFactory sf = new SSLSocketFactory(trusted);
        sf.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}

Un modo simple para convertir de JKS a BKS:

keytool -importkeystore -destkeystore cacerts.bks -deststoretype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk16-141.jar -deststorepass changeit -srcstorepass changeit -srckeystore $JAVA_HOME/jre/lib/security/cacerts -srcstoretype JKS -noprompt

* Nota: en Android 4.0 (ICS) la Trust Store ha cambiado, más información: http://nelenkov.blogspot.com.es/2011/12/ics-trust-store-implementation.html

ggrandes
fuente
3

Para aquellos que desean permitir que todos los certificados funcionen (con fines de prueba) sobre OAuth, siga estos pasos:

1) Descargue el código fuente de la API de Android OAuth aquí: https://github.com/kaeppler/signpost

2) Busque el archivo "CommonsHttpOAuthProvider" clase

3) Cámbielo de la siguiente manera:

public class CommonsHttpOAuthProvider extends AbstractOAuthProvider {

private static final long serialVersionUID = 1L;

private transient HttpClient httpClient;

public CommonsHttpOAuthProvider(String requestTokenEndpointUrl, String accessTokenEndpointUrl,
        String authorizationWebsiteUrl) {
    super(requestTokenEndpointUrl, accessTokenEndpointUrl, authorizationWebsiteUrl);


    //this.httpClient = new DefaultHttpClient();//Version implemented and that throws the famous "javax.net.ssl.SSLException: Not trusted server certificate" if the certificate is not signed with a CA
    this.httpClient = MySSLSocketFactory.getNewHttpClient();//This will work with all certificates (for testing purposes only)
}

El "MySSLSocketFactory" anterior se basa en la respuesta aceptada. Para hacerlo aún más fácil, aquí va la clase completa:

package com.netcomps.oauth_example;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;

//http://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https
public class MySSLSocketFactory extends SSLSocketFactory {

    SSLContext sslContext = SSLContext.getInstance("TLS");

public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {

    super(truststore);
    TrustManager tm = new X509TrustManager() {

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

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

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

    sslContext.init(null, new TrustManager[] { tm }, null);
}

@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
    return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}

@Override
public Socket createSocket() throws IOException {
    return sslContext.getSocketFactory().createSocket();
}



public static HttpClient getNewHttpClient() {

    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);

        SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);

    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}

}

Espero que esto ayude a alguien.

Tiago
fuente
1
La pregunta era HttpClienty HTTPS; no OAuth para Android de un proyecto GitHub.
jww
3

Usé esto y funciona para mí en todos los sistemas operativos.

/**
 * Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to
 * aid testing on a local box, not for use on production.
 */


private static void disableSSLCertificateChecking() {
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }
    } };

    try {
        SSLContext sc = SSLContext.getInstance("TLS");

        sc.init(null, trustAllCerts, new java.security.SecureRandom());

        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}
Baiju Sharma
fuente
Hola @ yegor256, estoy usando este código, pero sigo teniendo un problema de protocolo de enlace SSL
usuario2028
0

Cualquier persona que todavía tenga problemas con los Certificados SSL de StartCom en Android 2.1 visite https://www.startssl.com/certs/ y descargue ca.pem, ahora en la respuesta proporcionada por @emmby replace

`export CLASSPATH=bcprov-jdk16-145.jar
 CERTSTORE=res/raw/mystore.bks
      if [ -a $CERTSTORE ]; then
          rm $CERTSTORE || exit 1
      fi
 keytool \
  -import \
  -v \
  -trustcacerts \
  -alias 0 \
  -file <(openssl x509 -in mycert.pem) \
  -keystore $CERTSTORE \
  -storetype BKS \
  -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
  -providerpath /usr/share/java/bcprov.jar \
  -storepass some-password`

con

 `export CLASSPATH=bcprov-jdk16-145.jar
 CERTSTORE=res/raw/mystore.bks
      if [ -a $CERTSTORE ]; then
          rm $CERTSTORE || exit 1
      fi
 keytool \
  -import \
  -v \
  -trustcacerts \
  -alias 0 \
  -file <(openssl x509 -in ca.pem) \
  -keystore $CERTSTORE \
  -storetype BKS \
  -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
  -providerpath /usr/share/java/bcprov.jar \
  -storepass some-password`

Debería funcionar fuera de la caja. Estuve luchando por más de un día, incluso después de una respuesta perfecta de @emmby ... Espero que esto ayude a alguien ...

13hsoj
fuente
0

usa esta clase

public class WCFs
{
    //  https://192.168.30.8/myservice.svc?wsdl
private static final String NAMESPACE = "http://tempuri.org/";
private static final String URL = "192.168.30.8";
private static final String SERVICE = "/myservice.svc?wsdl";
private static String SOAP_ACTION = "http://tempuri.org/iWCFserviceMe/";


public static Thread myMethod(Runnable rp)
{
    String METHOD_NAME = "myMethod";

    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

    request.addProperty("Message", "Https WCF Running...");
    return _call(rp,METHOD_NAME, request);
}

protected static HandlerThread _call(final RunProcess rp,final String METHOD_NAME, SoapObject soapReq)
{
    final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    int TimeOut = 5*1000;

    envelope.dotNet = true;
    envelope.bodyOut = soapReq;
    envelope.setOutputSoapObject(soapReq);

    final HttpsTransportSE httpTransport_net = new HttpsTransportSE(URL, 443, SERVICE, TimeOut);

    try
    {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() // use this section if crt file is handmake
        {
            @Override
            public boolean verify(String hostname, SSLSession session)
            {
                return true;
            }
        });

        KeyStore k = getFromRaw(R.raw.key, "PKCS12", "password");
        ((HttpsServiceConnectionSE) httpTransport_net.getServiceConnection()).setSSLSocketFactory(getSSLSocketFactory(k, "SSL"));


    }
    catch(Exception e){}

    HandlerThread thread = new HandlerThread("wcfTd"+ Generator.getRandomNumber())
    {
        @Override
        public void run()
        {
            Handler h = new Handler(Looper.getMainLooper());
            Object response = null;

            for(int i=0; i<4; i++)
            {
                response = send(envelope, httpTransport_net , METHOD_NAME, null);

                try
                {if(Thread.currentThread().isInterrupted()) return;}catch(Exception e){}

                if(response != null)
                    break;

                ThreadHelper.threadSleep(250);
            }

            if(response != null)
            {
                if(rp != null)
                {
                    rp.setArguments(response.toString());
                    h.post(rp);
                }
            }
            else
            {
                if(Thread.currentThread().isInterrupted())
                    return;

                if(rp != null)
                {
                    rp.setExceptionState(true);
                    h.post(rp);
                }
            }

            ThreadHelper.stopThread(this);
        }
    };

    thread.start();

    return thread;
}


private static Object send(SoapSerializationEnvelope envelope, HttpTransportSE androidHttpTransport, String METHOD_NAME, List<HeaderProperty> headerList)
{
    try
    {
        if(headerList != null)
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope, headerList);
        else
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope);

        Object res = envelope.getResponse();

        if(res instanceof SoapPrimitive)
            return (SoapPrimitive) envelope.getResponse();
        else if(res instanceof SoapObject)
            return ((SoapObject) envelope.getResponse());
    }
    catch(Exception e)
    {}

    return null;
}

public static KeyStore getFromRaw(@RawRes int id, String algorithm, String filePassword)
{
    try
    {
        InputStream inputStream = ResourceMaster.openRaw(id);
        KeyStore keystore = KeyStore.getInstance(algorithm);
        keystore.load(inputStream, filePassword.toCharArray());
        inputStream.close();

        return keystore;
    }
    catch(Exception e)
    {}

    return null;
}

public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String SSLAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

        SSLContext context = SSLContext.getInstance(SSLAlgorithm);//"SSL" "TLS"
        context.init(null, tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }
    catch(Exception e){}

    return null;
}

}

Ali Bagheri
fuente
0

ingrese la descripción de la imagen aquí

Un sspi falló en xamarin android.

Encontré esta solución; ponga este código antes de presionar un enlace HTTPS

const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;
ServicePointManager.SecurityProtocol = Tls12;
vinothswami
fuente
-3

trabajar con todos los https

httpClient = new DefaultHttpClient();

SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
    public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

    public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

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

ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, ssf));
cezarius
fuente
2
Simplemente repite la misma falacia insegura no solución que ya se ha discutido y descartado en este hilo.
Marqués de Lorne
-3

Hay muchas respuestas anteriores, pero no pude hacer que ninguna de ellas funcionara correctamente (con mi tiempo limitado), por lo que para cualquier otra persona en la misma situación, puede probar el siguiente código que funcionó perfectamente para mis propósitos de prueba de Java:

    public static HttpClient wrapClient(HttpClient base) {
    try {
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

            public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        ctx.init(null, new TrustManager[]{tm}, null);
        SSLSocketFactory ssf = new SSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        ClientConnectionManager ccm = base.getConnectionManager();
        SchemeRegistry sr = ccm.getSchemeRegistry();
        sr.register(new Scheme("https", ssf, 443));
        return new DefaultHttpClient(ccm, base.getParams());
    } catch (Exception ex) {
        return null;
    }
}

y llama como:

DefaultHttpClient baseClient = new DefaultHttpClient();
HttpClient httpClient = wrapClient(baseClient );

Referencia: http://tech.chitgoks.com/2011/04/24/how-to-avoid-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-problem-using-apache-httpclient/

impostor
fuente
Para citar a EJP: "Simplemente repite la misma falta de solución insegura y falaz que ya se ha discutido y descartado en este hilo" .
jww
-4

Simplemente use esto:

public DefaultHttpClient wrapClient(HttpClient base) {
    try {
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

        public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };
    ctx.init(null, new TrustManager[]{tm}, null);
    SSLSocketFactory ssf = new SSLSocketFactory(ctx);
    ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    ClientConnectionManager ccm = base.getConnectionManager();
    SchemeRegistry sr = ccm.getSchemeRegistry();
    sr.register(new Scheme("https", ssf, 443));
    return new DefaultHttpClient(ccm, base.getParams());
} catch (Exception ex) {
    return null;
}
}
Hemant
fuente
Para citar a EJP: "Simplemente repite la misma falta de solución insegura y falaz que ya se ha discutido y descartado en este hilo" .
jww
-5

La respuesta de Daniel fue buena, excepto que tuve que cambiar este código ...

    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    registry.register(new Scheme("https", sf, 443));

    ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

a este código ...

    ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
    SchemeRegistry registry = ccm.getShemeRegistry()
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    registry.register(new Scheme("https", sf, 443));

para que funcione.

Dean Hiller
fuente
55
¿Cómo debería funcionar eso? usted hace referencia al registro antes incluso de haberlo creado!
Matthias B