Affidabilità di tutti i certificati tramite HttpClient su HTTPS


393

Di recente ha pubblicato una domanda riguardante l' HttpClientHttps ( disponibile qui ). Ho fatto qualche passo avanti, ma ho riscontrato nuovi problemi. Come per il mio ultimo problema, non riesco a trovare un esempio che funzioni per me. Fondamentalmente, voglio che il mio client accetti qualsiasi certificato (perché sto puntando sempre solo su un server) ma continuo a ottenere unjavax.net.ssl.SSLException: Not trusted server certificate exception.

Quindi questo è quello che ho:


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

Ed ecco l'errore che sto ricevendo:

    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

17
Ho dovuto farlo per uso interno. Spero davvero che non lascerai che gli utenti esterni alla tua azienda utilizzino la tua app da quando l'hai aperta a man in the middle attack e sarebbero quindi vulnerabili a qualcuno che ha dirottato la loro sessione. tuttavia, ho bisogno di fare questo temporaneo per alcuni test fino a quando non avrò il vero certificato in mano ..... speriamo che lo stiate facendo per lo stesso tipo di motivo temporaneo o l'app viene utilizzata solo internamente.
Dean Hiller,

Ho provato queste soluzioni sul client HTTP Apache 4.3, ma sono per lo più deprecate. Qui non è deprecato soluzione: stackoverflow.com/a/18941950/2039471
Alexander Chzhen

Java 1.6 non ha il supporto SNI che è anche problematico in questi scenari - se non si costruisce la richiesta correttamente, è possibile ottenere un certificato che non corrisponde alla richiesta. Vedi issues.apache.org/jira/browse/HTTPCLIENT-1119
Bron Davies

2
Questa domanda è citata nel documento The Most Dangerous Code in the World come esempio di ragionamento fallace. (documento di ricerca: cs.utexas.edu/~shmat/shmat_ccs12.pdf )
mk_

Risposte:


421

Nota: non implementarlo nel codice di produzione che verrà mai utilizzato su una rete di cui non si fida completamente. Soprattutto tutto ciò che accade su Internet pubblico.

La tua domanda è proprio quello che voglio sapere. Dopo aver fatto alcune ricerche, la conclusione è la seguente.

In modo HttpClient, è necessario creare una classe personalizzata da org.apache.http.conn.ssl.SSLSocketFactory, non quella org.apache.http.conn.ssl.SSLSocketFactory stessa. Alcuni indizi sono disponibili in questo post La gestione SSL personalizzata ha smesso di funzionare su Android 2.2 FroYo .

Un esempio è come ...

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

e utilizzare questa classe durante la creazione dell'istanza di 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();
    }
}

A proposito, il link qui sotto è per qualcuno che sta cercando la soluzione di connessione HttpURLC. Connessione Https Android

Ho testato i due suddetti tipi di soluzioni su froyo e tutti funzionano come un incantesimo nei miei casi. Infine, l'utilizzo di HttpURLConnection può affrontare i problemi di reindirizzamento, ma questo va oltre l'argomento.

Nota: prima di decidere di fidarsi di tutti i certificati, probabilmente dovresti conoscere bene il sito e non ne sarà dannoso per l'utente finale.

In effetti, il rischio che prendi dovrebbe essere considerato attentamente, compreso l'effetto del sito fittizio degli hacker menzionato nei seguenti commenti che ho molto apprezzato. In alcune situazioni, anche se potrebbe essere difficile prendersi cura di tutti i certificati, è meglio conoscere gli svantaggi impliciti di fidarsi di tutti.


150
questa risposta dovrebbe probabilmente notare che la fiducia in tutti i certificati è terribilmente insicura e annulla l'intero scopo di ssl ...
yanokwa,

22
@sweeney - Tranne che non è garantito che stai parlando con il server che pensi di essere. Se qualcuno ha creato un server DNS, potresti comunicare una chiave di crittografia con il server di un hacker.
Richard Szalay,

12
@sweeney In altre parole, ora sei responsabile di attacchi man-in-the-middle. Dovresti anche notare che quel codice non soddisfa le specifiche: controlla Javadoc. getAcceptedIssuers()non è consentito restituire null.
Marchese di Lorne,

25
-1 Perché è una pessima idea accettare tutti i certificati. È un peccato che ci siano così tanti blog e tutorial che guidano felicemente gli sviluppatori Java lungo il percorso di fare la cosa sbagliata.
Tim Bender,

57
+1 Perché avevo bisogno di una soluzione rapida solo a scopo di debug. Non lo userei in produzione a causa dei problemi di sicurezza che altri hanno menzionato, ma questo era esattamente ciò di cui avevo bisogno per i test. Grazie!
Danni

495

Fondamentalmente hai quattro potenziali soluzioni per correggere un'eccezione "Non attendibile" su Android usando httpclient:

  1. Fidati di tutti i certificati. Non farlo, a meno che tu non sappia davvero cosa stai facendo.
  2. Crea un SSLSocketFactory personalizzato che si fida solo del tuo certificato. Funziona fintanto che sai esattamente a quali server ti collegherai, ma non appena dovrai connetterti a un nuovo server con un diverso certificato SSL, dovrai aggiornare la tua app.
  3. Crea un file keystore che contenga la "lista principale" di certificati Android, quindi aggiungi il tuo. Se qualcuno di questi certificati scade lungo la strada, sei responsabile di aggiornarli nella tua app. Non riesco a pensare a un motivo per farlo.
  4. Crea un SSLSocketFactory personalizzato che utilizza il KeyStore certificato incorporato, ma ricade su un KeyStore alternativo per tutto ciò che non riesce a verificare con il valore predefinito.

Questa risposta utilizza la soluzione n. 4, che mi sembra la più solida.

La soluzione consiste nell'utilizzare un SSLSocketFactory che può accettare più KeyStores, consentendo di fornire al proprio KeyStore i propri certificati. Ciò consente di caricare certificati aggiuntivi di livello superiore come Thawte che potrebbero mancare su alcuni dispositivi Android. Inoltre, consente di caricare i propri certificati autofirmati. Utilizzerà prima i certificati predefiniti dei dispositivi integrati e ricadrà sui certificati aggiuntivi solo se necessario.

Innanzitutto, dovrai determinare quale certificato ti manca nel tuo KeyStore. Esegui il seguente comando:

openssl s_client -connect www.yourserver.com:443

E vedrai un output come il seguente:

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

Come puoi vedere, il nostro certificato di root è di Thawte. Vai al sito Web del tuo provider e trova il certificato corrispondente. Per noi, era qui e puoi vedere che quello di cui avevamo bisogno era quello Copyright 2006.

Se si utilizza un certificato autofirmato, non è necessario eseguire il passaggio precedente poiché si dispone già del certificato di firma.

Quindi, creare un file keystore contenente il certificato di firma mancante. Crazybob ha dettagli su come farlo su Android , ma l'idea è di fare quanto segue:

Se non lo possiedi già, scarica la libreria del provider di castelli gonfiabili da: http://www.bouncycastle.org/latest_releases.html . Questo andrà sul tuo percorso di classe qui sotto.

Esegui un comando per estrarre il certificato dal server e creare un file pem. In questo caso, mycert.pem.

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

Quindi eseguire i comandi seguenti per creare il keystore.

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

Noterai che lo script sopra inserisce il risultato res/raw/mystore.bks. Ora hai un file che caricherai nella tua app Android che fornisce i certificati mancanti.

Per fare ciò, registra SSLSocketFactory per lo schema 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);

Per creare 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);
    }
}

Infine, il codice AdditionalKeyStoresSSLSocketFactory, che accetta il tuo nuovo KeyStore e verifica se il KeyStore integrato non riesce a convalidare un certificato 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()]);
        }
    }

}

Ehi @emmby, questa sembra essere la risposta perfetta per il mio problema, ma non ho ancora nessuna connessione SSL. Puoi per favore dare un'occhiata a questo? http://stackoverflow.com/questions/7822381/need-help-understanding-certificate-chains
Matthias B,

Grazie per l'ottimo commento @emmby! A volte ricevo un ritardo davvero lungo e quindi un javax.net.ssl.SSLException: errore di lettura :. Qualche idea? Come posso impostare un timeout se la soluzione è uguale a stackoverflow.com/questions/5909308/android-2-3-4-ssl-problem ?
Edwin Evans,

3
@emmby, potresti dire dove devo mettere questo codice export CLASSPATH = bcprov-jdk16-145.jar CERTSTORE = res / raw / mystore.bks if [-a $ CERTSTORE]; quindi 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
Rikki Tikki Tavi

1
Ehi @emmby. Sto usando la tua soluzione nella mia app e sto usando il certificato autofirmato del mio server ma sto ottenendo un CertificateException () nel metodo checkServerTrusted () . Ho provato a commentare quell'eccezione, e funziona. se non convalida il mio cert del server, allora posso gestirlo in altro modo, puoi per favore guidare qual è la soluzione migliore in questo caso?
Ankit

7
Questo dovrebbe essere contrassegnato come la risposta giusta. Una delle risposte più complete e ben scritte che abbia mai visto su SO. Dope
Kachi,

74

Aggiungi questo codice prima di HttpsURLConnectione sarà fatto. Capito.

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

Spero che questo ti aiuta.


22
Vedi le osservazioni sopra nella risposta accettata. Questa "soluzione" è radicalmente insicura.
Marchese di Lorne,

5
Questa è la soluzione di domande e risposte ideale. Corto e "funziona".
Steve Smith,

5
Risposta perfetta a scopo di test !!! E sì, è una cattiva idea da usare in produzione, ma dai ... questo dovrebbe essere chiaro a tutti quelli che guardano il titolo della domanda. Risponde ancora meglio / più breve / con lo stesso livello di sicurezza (in)!
Levita,

34

Questa è una cattiva idea. Fidarsi di qualsiasi certificato è solo (molto) leggermente meglio che non usare affatto SSL. Quando dici "Voglio che il mio cliente accetti qualsiasi certificato (perché sto puntando sempre su un solo server)" stai assumendo questo significa che in qualche modo indicare "un server" è sicuro, che non è su una rete pubblica.

Sei completamente aperto a un attacco man-in-the-middle fidandoti di qualsiasi certificato. Chiunque può eseguire il proxy della connessione stabilendo una connessione SSL separata con te e con il server finale. Il MITM ha quindi accesso a tutta la tua richiesta e risposta. A meno che tu non abbia realmente bisogno di SSL in primo luogo (il tuo messaggio non ha nulla di sensibile e non fa autenticazione) non dovresti fidarti di tutti i certificati alla cieca.

Dovresti considerare di aggiungere il certificato pubblico a un jks usando keytool e di usarlo per costruire il tuo factory socket, come questo:

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

Questo ha un avvertimento a cui fare attenzione. Alla fine il certificato scadrà e il codice smetterà di funzionare in quel momento. Puoi facilmente determinare quando ciò accadrà guardando il certificato.


5
Se non si utilizza l'autenticazione con certificato client, dal lato client, non è necessario un gestore delle chiavi (utilizzare nullin SSLContext.init). You should also use the default algorithms (KMF/TMF.getDefaultAlgorithm() ), instead of hard-coding SunX509` (soprattutto perché l'impostazione predefinita per TMF è in realtà PKIXsu Sun / Oracle JVM).
Bruno

Esiste un file di certificati radice pronto all'uso? (come fanno i browser)
dani herrera il

Da dove myjks.jksviene?
zionpi,

1
@zionpi Generato utilizzando "keytool" Java.
Dan,

22

Puoi disabilitare il controllo SSL di HttpURLConnection a scopo di test in questo modo dall'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());
    }

2
org.apache.http.conn.ssl.AllowAllHostnameVerifierè deprecato.
zackygaurav,

2
@zackygaurav Secondo javadoc , AllowAllHostnameVerifierè sostituito da NoopHostnameVerifier"
DLight

10

L'API di HttpComponents è stata modificata. Funziona con il codice seguente.

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

L'uso di una strategia di fiducia personalizzata è la risposta giusta. Grazie.
Matt Friedman,

10

Il codice sopra in https://stackoverflow.com/a/6378872/1553004 è corretto, tranne che DEVE anche chiamare il verificatore del nome 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;
}

Mi sono iscritto a StackOverflow espressamente per aggiungere questa correzione. Ascolta il mio avvertimento!


Dopo aver verificato il certificato in questo modo sulla prima connessione, cosa si fa con le connessioni successive? Sfruttate le conoscenze acquisite dalla prima connessione? Cosa succede se viene utilizzato un certificato falso con lo stesso nome durante il tentativo di connessione 3?
jww

6

Sto aggiungendo una risposta per coloro che usano httpclient-4.5 e probabilmente funziona anche per 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);
    }
}
}

che cos'è la nuova classe NoopHostnameVerifier ()?
Mushtakim Ahmed Ansari,

1
@MushtakimAhmedAnsari Da docs: "NO_OP HostnameVerifier essenzialmente disattiva la verifica del nome host. Questa implementazione è no-op e non getta mai SSLException."
raisercostin,

Grazie per l'ottima risposta. Questo dovrebbe ottenere più voti.
Abhay Dwivedi,

Come lo uso? o stai suggerendo che semplicemente avere la classe avrà la precedenza sulle verifiche del certificato SSL?
Behelit,

sì. che httpClient quando usato non convaliderà i certificati https
raisercostin

4

Fidarsi di tutti i certificati non è stata una vera alternativa per me, quindi ho fatto quanto segue per convincere HttpsURLConnection a fidarsi di un nuovo certificato (vedi anche http://nelenkov.blogspot.jp/2011/12/using-custom-certificate-trust-store- on.html ).

  1. Ottieni il certificato; Ho ottenuto questo risultato esportando il certificato in Firefox (fare clic sulla piccola icona a forma di lucchetto, ottenere i dettagli del certificato, fare clic su Esporta), quindi utilizzare portecle per esportare un truststore (BKS).

  2. Carica il Truststore da /res/raw/geotrust_cert.bks con il seguente codice:

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

Ottengo questo errore. IOExceptionjavax.net.ssl.SSLPeerUnverifiedException: No peer certificate. Questo quando si esegue la chiamata di esecuzione effettiva su HttpClient dopo aver eseguito l'installazione sopra.
Michael,

3

Ecco una versione molto semplice usando il codice httpclient 4.1.2. Questo può quindi essere modificato in qualsiasi algoritmo di trust che ritieni opportuno.

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

3

Sono stato cercato risposta da "emmby" (risposta 16 giugno 11 alle 21:29), elemento n. 4: "Crea un SSLSocketFactory personalizzato che utilizza il KeyStore certificato incorporato, ma ricade su un KeyStore alternativo per qualsiasi errore per verificare con il valore predefinito. "

Questa è un'implementazione semplificata. Carica il keystore di sistema e uniscilo con il keystore dell'applicazione.

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

Una modalità semplice per convertire da 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: in Android 4.0 (ICS) il Trust Store è cambiato, maggiori informazioni: http://nelenkov.blogspot.com.es/2011/12/ics-trust-store-implementation.html


3

Per coloro che desiderano consentire a tutti i certificati di funzionare (a scopo di test) su OAuth, attenersi alla seguente procedura:

1) Scarica il codice sorgente dell'API OAuth per Android qui: https://github.com/kaeppler/signpost

2) Trova il file "CommonsHttpOAuthProvider" classe

3) Modificalo come di seguito:

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

"MySSLSocketFactory" sopra si basa sulla risposta accettata. Per rendere ancora più semplice, ecco la classe 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();
    }
}

}

Spero che questo aiuti qualcuno.


1
La domanda era HttpCliente HTTPS; non OAuth per Android da un progetto GitHub.
j

3

L'ho usato e funziona per me su tutti i sistemi operativi.

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

Ciao @ yegor256, sto usando questo codice, ma ho ancora problemi di stretta di mano SSL
user2028


0

Qualsiasi organismo che ancora lotta con i certificati SSL StartCom su Android 2.1 visita https://www.startssl.com/certs/ e scarica ca.pem, ora nella risposta fornita da @emmby sostituisci

`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`

Dovrebbe funzionare fuori dalla scatola. Ho lottato per oltre un giorno anche dopo una risposta perfetta di @emmby .. Spero che questo aiuti qualcuno ...


0

usa questa classe

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

}


0

inserisci qui la descrizione dell'immagine

Uno sspi fallito in Android Xamarin.

Ho trovato questa soluzione; inserisci questo codice prima di premere su un collegamento HTTPS

const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;
ServicePointManager.SecurityProtocol = Tls12;

-3

funziona con tutti gli 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));

2
Ripete semplicemente la stessa fallace insicura non soluzione che è già stata discussa e respinta in questo thread.
Marchese di Lorne,

-3

Ci sono molte risposte sopra ma non sono riuscito a far funzionare correttamente nessuno di loro (con il mio tempo limitato), quindi per chiunque nella stessa situazione puoi provare il codice qui sotto che ha funzionato perfettamente per i miei scopi di test 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;
    }
}

e chiama come:

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

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


Per citare EJP: "Basta ripetere la stessa fallace insicura non soluzione che è già stata discussa e respinta in questo thread" .
j

-4

Basta usare questo -

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

Per citare EJP: "Basta ripetere la stessa fallace insicura non soluzione che è già stata discussa e respinta in questo thread" .
j

-5

La risposta di Daniel è stata buona, tranne per il fatto che ho dovuto cambiare questo codice ...

    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 questo codice ...

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

per farlo funzionare.


5
come dovrebbe funzionare? fai riferimento al registro prima ancora di crearlo!
Matthias B,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.