accettare connessioni HTTPS con certificati autofirmati


153

Sto cercando di stabilire connessioni HTTPS, usando HttpClientlib, ma il problema è che, poiché il certificato non è firmato da un'autorità di certificazione riconosciuta ( Verisign , GlobalSIgn , ecc. ) , Elencato sul set di certificati attendibili Android, Continuo a riceverejavax.net.ssl.SSLException: Not trusted server certificate .

Ho visto soluzioni in cui accetti semplicemente tutti i certificati, ma cosa succede se voglio chiedere all'utente?

Voglio ottenere una finestra di dialogo simile a quella del browser, lasciando che l'utente decida di continuare o meno. Preferibilmente, vorrei utilizzare lo stesso negozio di certificati del browser. Qualche idea?


Questa soluzione accettata ha funzionato per me- stackoverflow.com/questions/2642777/…
Venkatesh,

Risposte:


171

La prima cosa che devi fare è impostare il livello di verifica. Tali livelli non sono così tanto:

  • ALLOW_ALL_HOSTNAME_VERIFIER
  • BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
  • STRICT_HOSTNAME_VERIFIER

Sebbene il metodo setHostnameVerifier () sia obsoleto per la nuova libreria apache, ma per la versione in Android SDK è normale. E così lo prendiamo ALLOW_ALL_HOSTNAME_VERIFIERe lo impostiamo nella fabbrica dei metodi SSLSocketFactory.setHostnameVerifier().

Successivamente, è necessario impostare la nostra fabbrica per il protocollo su https. Per fare questo, basta chiamare ilSchemeRegistry.register() metodo.

Quindi è necessario creare un DefaultHttpClientcon SingleClientConnManager. Anche nel codice qui sotto puoi vedere che di default utilizzerà anche il nostro flag ( ALLOW_ALL_HOSTNAME_VERIFIER) con il metodoHttpsURLConnection.setDefaultHostnameVerifier()

Di seguito il codice funziona per me:

HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

DefaultHttpClient client = new DefaultHttpClient();

SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());

// Set verifier     
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

// Example send http request
final String url = "https://encrypted.google.com/";
HttpPost httpPost = new HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);

6
Purtroppo non riesco a far funzionare questo codice, ricevo ancora il "Certificato server non attendibile". Ci sono permessi extra che devo impostare per farlo funzionare?
Juriy,

1
Questo codice non accetta solo tutti i certificati? Ho bisogno di un popup per accettarlo.
Morten,

3
Sto usando org.apache.http.conn.ssl.SSLSocketFactoryperché voglio usare javax.net.ssl.HttpsURLConnection??
Qualcuno da qualche parte

9
Puoi spiegare in che modo questo codice è meglio che disabilitare del tutto la verifica del certificato? Non ho familiarità con l'API ssl di Android, ma a prima vista questo sembra completamente insicuro contro gli aggressori attivi.
Codici InCos

3
Suggerirei di utilizzare ThreadSafeClientConnManager invece di SingleClientConnManager
Farm

124

I seguenti passaggi principali sono necessari per ottenere una connessione protetta dalle autorità di certificazione che non sono considerate affidabili dalla piattaforma Android.

Come richiesto da molti utenti, ho rispecchiato le parti più importanti del mio articolo di blog qui:

  1. Prendi tutti i certificati richiesti (root e qualsiasi CA intermedia)
  2. Crea un keystore con keytool e BouncyCastle provider e importa i certificati
  3. Carica il keystore nella tua app Android e usalo per le connessioni protette (ti consiglio di usare Apache HttpClient invece dello standard java.net.ssl.HttpsURLConnection(più facile da capire, più performante)

Prendi le certs

È necessario ottenere tutti i certificati che creano una catena dal certificato endpoint fino alla CA principale. Ciò significa che tutti i certificati CA intermedi (se presenti) e anche il certificato CA radice. Non è necessario ottenere il certificato endpoint.

Crea il keystore

Scarica il provider BouncyCastle e memorizzalo in una posizione nota. Assicurati anche di poter invocare il comando keytool (solitamente situato nella cartella bin dell'installazione di JRE).

Ora importa le certs ottenute (non importare il certificato endpoint) in un keystore formattato BouncyCastle.

Non l'ho provato, ma penso che l'ordine di importazione dei certificati sia importante. Ciò significa, importare prima il certificato CA intermedio più basso e poi fino al certificato CA principale.

Con il comando seguente un nuovo keystore (se non già presente) con la password verrà creato mysecret e verrà importato il certificato CA intermedio. Ho anche definito il provider BouncyCastle, dove può essere trovato sul mio file system e sul formato del keystore. Eseguire questo comando per ciascun certificato nella catena.

keytool -importcert -v -trustcacerts -file "path_to_cert/interm_ca.cer" -alias IntermediateCA -keystore "res/raw/mykeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret

Verifica se i certificati sono stati importati correttamente nel keystore:

keytool -list -keystore "res/raw/mykeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret

Dovrebbe produrre l'intera catena:

RootCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 24:77:D9:A8:91:D1:3B:FA:88:2D:C2:FF:F8:CD:33:93
IntermediateCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43

Ora puoi copiare il keystore come risorsa non elaborata nella tua app Android sotto res/raw/

Usa il keystore nella tua app

Prima di tutto dobbiamo creare un Apache HttpClient personalizzato che utilizza il nostro keystore per le connessioni HTTPS:

import org.apache.http.*

public class MyHttpClient extends DefaultHttpClient {

    final Context context;

    public MyHttpClient(Context context) {
        this.context = context;
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        // Register for port 443 our SSLSocketFactory with our keystore
        // to the ConnectionManager
        registry.register(new Scheme("https", newSslSocketFactory(), 443));
        return new SingleClientConnManager(getParams(), registry);
    }

    private SSLSocketFactory newSslSocketFactory() {
        try {
            // Get an instance of the Bouncy Castle KeyStore format
            KeyStore trusted = KeyStore.getInstance("BKS");
            // Get the raw resource, which contains the keystore with
            // your trusted certificates (root and any intermediate certs)
            InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
            try {
                // Initialize the keystore with the provided trusted certificates
                // Also provide the password of the keystore
                trusted.load(in, "mysecret".toCharArray());
            } finally {
                in.close();
            }
            // Pass the keystore to the SSLSocketFactory. The factory is responsible
            // for the verification of the server certificate.
            SSLSocketFactory sf = new SSLSocketFactory(trusted);
            // Hostname verification from certificate
            // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
            sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
            return sf;
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

Abbiamo creato il nostro HttpClient personalizzato, ora possiamo usarlo per connessioni sicure. Ad esempio, quando effettuiamo una chiamata GET a una risorsa REST:

// Instantiate the custom HttpClient
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://www.mydomain.ch/rest/contacts/23");
// Execute the GET call and obtain the response
HttpResponse getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();

Questo è tutto ;)


8
Questo è utile solo per ottenere certificati prima di spedire la tua applicazione. Non aiuta davvero gli utenti ad accettare i propri certificati. per la tua applicazione
Fuzzy

Ciao a tutti qualcuno può dirmi il processo di convalida per keystore con truststore per l'implementazione di cui sopra ??? grazie in anticipo ..
andriod_testing

Questo ha funzionato bene ... ma ora sto affrontando un problema quando ricomprimo il certificato sul server. Sembra strano che ogni volta che aggiorno il certificato sul mio server, anche l'archivio lato client debba essere aggiornato. Deve esserci un modo migliore: |
bpn,

Risposta Gr8, suggerirei di utilizzare ThreadSafeClientConnManager invece di SingleClientConnManager
Farm

Ho aggiunto /res/raw/mykeystore.bks, sebbene incapace di risolvere il riferimento ad esso. come risolverlo?
uniruddh,

16

Se hai un certificato personalizzato / autofirmato sul server che non è presente sul dispositivo, puoi utilizzare la classe seguente per caricarlo e utilizzarlo sul lato client in Android:

Inserire il *.crtfile del certificato in /res/rawmodo che sia disponibile daR.raw.*

Utilizzare la classe seguente per ottenere un HTTPCliento HttpsURLConnectionche disporrà di una factory socket utilizzando quel certificato:

package com.example.customssl;

import android.content.Context;
import org.apache.http.client.HttpClient;
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.AllowAllHostnameVerifier;
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 javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

public class CustomCAHttpsProvider {

    /**
     * Creates a {@link org.apache.http.client.HttpClient} which is configured to work with a custom authority
     * certificate.
     *
     * @param context       Application Context
     * @param certRawResId  R.raw.id of certificate file (*.crt). Should be stored in /res/raw.
     * @param allowAllHosts If true then client will not check server against host names of certificate.
     * @return Http Client.
     * @throws Exception If there is an error initializing the client.
     */
    public static HttpClient getHttpClient(Context context, int certRawResId, boolean allowAllHosts) throws Exception {


        // build key store with ca certificate
        KeyStore keyStore = buildKeyStore(context, certRawResId);

        // init ssl socket factory with key store
        SSLSocketFactory sslSocketFactory = new SSLSocketFactory(keyStore);

        // skip hostname security check if specified
        if (allowAllHosts) {
            sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier());
        }

        // basic http params for client
        HttpParams params = new BasicHttpParams();

        // normal scheme registry with our ssl socket factory for "https"
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));

        // create connection manager
        ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);

        // create http client
        return new DefaultHttpClient(cm, params);
    }

    /**
     * Creates a {@link javax.net.ssl.HttpsURLConnection} which is configured to work with a custom authority
     * certificate.
     *
     * @param urlString     remote url string.
     * @param context       Application Context
     * @param certRawResId  R.raw.id of certificate file (*.crt). Should be stored in /res/raw.
     * @param allowAllHosts If true then client will not check server against host names of certificate.
     * @return Http url connection.
     * @throws Exception If there is an error initializing the connection.
     */
    public static HttpsURLConnection getHttpsUrlConnection(String urlString, Context context, int certRawResId,
                                                           boolean allowAllHosts) throws Exception {

        // build key store with ca certificate
        KeyStore keyStore = buildKeyStore(context, certRawResId);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);

        // Create a connection from url
        URL url = new URL(urlString);
        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
        urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());

        // skip hostname security check if specified
        if (allowAllHosts) {
            urlConnection.setHostnameVerifier(new AllowAllHostnameVerifier());
        }

        return urlConnection;
    }

    private static KeyStore buildKeyStore(Context context, int certRawResId) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
        // init a default key store
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);

        // read and add certificate authority
        Certificate cert = readCert(context, certRawResId);
        keyStore.setCertificateEntry("ca", cert);

        return keyStore;
    }

    private static Certificate readCert(Context context, int certResourceId) throws CertificateException, IOException {

        // read certificate resource
        InputStream caInput = context.getResources().openRawResource(certResourceId);

        Certificate ca;
        try {
            // generate a certificate
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            ca = cf.generateCertificate(caInput);
        } finally {
            caInput.close();
        }

        return ca;
    }

}

Punti chiave:

  1. Certificategli oggetti sono generati da .crtfile.
  2. Viene KeyStorecreato un valore predefinito .
  3. keyStore.setCertificateEntry("ca", cert)sta aggiungendo il certificato all'archivio chiavi sotto l'alias "ca". Si modifica il codice per aggiungere più certificati (CA intermedia ecc.).
  4. L'obiettivo principale è quello di generare un SSLSocketFactoryche può quindi essere utilizzato da HTTPClientoHttpsURLConnection .
  5. SSLSocketFactory può essere ulteriormente configurato, ad esempio per saltare la verifica del nome host ecc.

Maggiori informazioni su: http://developer.android.com/training/articles/security-ssl.html


Dove posso trovare i .crtfile? Scarica da un server?
zionpi,

@zionpi Il file del certificato sarà lo stesso utilizzato dal server abilitato TLS a cui ci si sta connettendo.
SD

Grazie! È stato così facile!
Kapil Thadani,

@SD Come posso usare il file .P12 invece di .crt?
Rakesh R Nair,

Ho un simile freddo dubbio si prega di aiuto stackoverflow.com/questions/57389622/...
StezPet

8

Ero frustrato nel provare a connettere la mia app Android al mio servizio RESTful usando https. Inoltre ero un po 'seccato per tutte le risposte che suggerivano di disabilitare del tutto il controllo dei certificati. Se lo fai, qual è il punto di https?

Dopo aver cercato su Google l'argomento per un po ', ho finalmente trovato questa soluzione in cui non sono necessari barattoli esterni, solo API Android. Grazie ad Andrew Smith, che lo ha pubblicato a luglio 2014

 /**
 * Set up a connection to myservice.domain using HTTPS. An entire function
 * is needed to do this because myservice.domain has a self-signed certificate.
 * 
 * The caller of the function would do something like:
 * HttpsURLConnection urlConnection = setUpHttpsConnection("https://littlesvr.ca");
 * InputStream in = urlConnection.getInputStream();
 * And read from that "in" as usual in Java
 * 
 * Based on code from:
 * https://developer.android.com/training/articles/security-ssl.html#SelfSigned
 */
public static HttpsURLConnection setUpHttpsConnection(String urlString)
{
    try
    {
        // Load CAs from an InputStream
        // (could be from a resource or ByteArrayInputStream or ...)
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        // My CRT file that I put in the assets folder
        // I got this file by following these steps:
        // * Go to https://littlesvr.ca using Firefox
        // * Click the padlock/More/Security/View Certificate/Details/Export
        // * Saved the file as littlesvr.crt (type X.509 Certificate (PEM))
        // The MainActivity.context is declared as:
        // public static Context context;
        // And initialized in MainActivity.onCreate() as:
        // MainActivity.context = getApplicationContext();
        InputStream caInput = new BufferedInputStream(MainActivity.context.getAssets().open("littlesvr.crt"));
        Certificate ca = cf.generateCertificate(caInput);
        System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());

        // Create a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tmf.getTrustManagers(), null);

        // Tell the URLConnection to use a SocketFactory from our SSLContext
        URL url = new URL(urlString);
        HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
        urlConnection.setSSLSocketFactory(context.getSocketFactory());

        return urlConnection;
    }
    catch (Exception ex)
    {
        Log.e(TAG, "Failed to establish SSL connection to server: " + ex.toString());
        return null;
    }
}

Ha funzionato bene per la mia App di mockup.


X509Certificato quale dovrei importare java o javax?
Siddharth,

Ho importatoimport java.security.cert.X509Certificate;
Gonzalo Fernández il

Grazie per questo

6

La risposta migliore non ha funzionato per me. Dopo alcune indagini ho trovato le informazioni richieste su "Sviluppatore Android": https://developer.android.com/training/articles/security-ssl.html#SelfSigned

La creazione di un'implementazione vuota di X509TrustManager ha funzionato:

private static class MyTrustManager implements 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;
    }

}

...

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
try
{
    // Create an SSLContext that uses our TrustManager
    SSLContext context = SSLContext.getInstance("TLS");
    TrustManager[] tmlist = {new MyTrustManager()};
    context.init(null, tmlist, null);
    conn.setSSLSocketFactory(context.getSocketFactory());
}
catch (NoSuchAlgorithmException e)
{
    throw new IOException(e);
} catch (KeyManagementException e)
{
    throw new IOException(e);
}
conn.setRequestMethod("GET");
int rcode = conn.getResponseCode();

Si noti che questa vuota implementazione di TustManager è solo un esempio e l'utilizzo in un ambiente produttivo causerebbe una grave minaccia alla sicurezza!


1
fyi - idk se fosse così in quel momento, ma sembrano scoraggiare fortemente questo approccio ora (vedi la nota)
Saik Caskey

6

Google consiglia l'utilizzo di Android Volley per le connessioni HTTP / HTTPS , poiché HttpClientè obsoleto. Quindi conosci la scelta giusta :).

E inoltre, MAI i certificati SSL NUKE (MAI !!!).

Annullare il certificato SSL è totalmente contrario allo scopo di SSL, che promuove la sicurezza . Non ha senso usare SSL, se hai intenzione di bombardare tutti i certificati SSL che ne derivano. Una soluzione migliore sarebbe, non usando SSL, o una soluzione migliore, sarebbe creare un'abitudineTrustManager sulla tua App + utilizzando Android Volley per le connessioni HTTP / HTTPS.

Ecco un Gist che ho creato, con una LoginApp di base, eseguendo connessioni HTTPS, utilizzando un certificato autofirmato sul lato server, accettato sull'app.

Ecco anche un altro suggerimento che può aiutare, per la creazione di certificati SSL autofirmati per la configurazione sul server e l'utilizzo del certificato sulla tua app. Molto importante: devi copiare il file .crt che è stato generato dallo script sopra, nella directory "raw" dal tuo progetto Android.


Ciao Ivan, non ho mai lavorato con i certificati SSL. Ti andrebbe di elaborare un po ', come posso ottenere il file .crt?
jlively

Ciao Jively! Vedo. Sì, naturalmente. Ma prima, ti dispiacerebbe dare un'occhiata al secondo Gist che ho menzionato sopra? Ho messo due file su questo Gist: uno è il file utilizzato dallo script e l'altro, è lo script stesso, che utilizza il binario "openssl" per leggere il file e quindi, costruendo il file che contiene il certificato SSL ( .crt). Fammi sapere se sei riuscito a capire tutto. Saluti :).
Ivanleoncz,

Hmm, sì, ho esaminato quei 2 concetti, ma non riesco davvero a capire come li uso?
vivacemente il

4

Ecco come è possibile aggiungere ulteriori certificati al KeyStore per evitare questo problema: fidarsi di tutti i certificati usando HttpClient su HTTPS

Non verrà richiesto all'utente come richiesto, ma renderà meno probabile che si verifichi un errore "Certificato server non attendibile".


Solo a scopo di test, non puoi pubblicare un'app nel Play Store con questo trucco perché verrà rifiutata
ariel

3

Il modo più semplice per creare un certificato SSL

Apri Firefox (suppongo sia possibile anche con Chrome, ma è più facile per me con FF)

Visita il tuo sito di sviluppo con un certificato SSL autofirmato.

Fai clic sul certificato (accanto al nome del sito)

Fai clic su "Ulteriori informazioni"

Fai clic su "Visualizza certificato"

Clicca su "Dettagli"

Fai clic su "Esporta ..."

Scegli "Certificato X.509 con catena (PEM)", seleziona la cartella e il nome per salvarlo e fai clic su "Salva"

Vai alla riga di comando, nella directory in cui hai scaricato il file pem ed esegui "openssl x509 -inform PEM -outform DM -in .pem -out .crt"

Copia il file .crt nella cartella principale della cartella / sdcard all'interno del tuo dispositivo Android All'interno del tuo dispositivo Android, Impostazioni> Sicurezza> Installa da archivio.

Dovrebbe rilevare il certificato e consentirti di aggiungerlo al dispositivo Sfoglia il tuo sito di sviluppo.

La prima volta dovrebbe chiederti di confermare l'eccezione di sicurezza. È tutto.

Il certificato dovrebbe funzionare con qualsiasi browser installato sul tuo Android (Browser, Chrome, Opera, Dolphin ...)

Ricorda che se stai offrendo i tuoi file statici da un dominio diverso (siamo tutti speed bitch di pagine) devi anche aggiungere il certificato per quel dominio.


2

Ho scritto una piccola libreria ssl-utils-android per fidarmi di un certificato particolare su Android.

Puoi semplicemente caricare qualsiasi certificato fornendo il nome file dalla directory delle risorse.

Uso:

OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());

1

Nessuna di queste correzioni ha funzionato per la mia piattaforma di sviluppo destinata all'SDK 16, versione 4.1.2, quindi ho trovato una soluzione alternativa.

La mia app memorizza i dati sul server utilizzando " http://www.example.com/page.php?data=somedata "

Recentemente page.php è stato spostato su " https://www.secure-example.com/page.php " e continuo a ricevere "javax.net.ssl.SSLException: certificato server non attendibile".

Invece di accettare tutti i certificati solo per una singola pagina, a partire da questa guida ho risolto il mio problema scrivendo il mio page.php pubblicato su " http://www.example.com/page.php "

<?php

caronte ("https://www.secure-example.com/page.php");

function caronte($url) {
    // build curl request
    $ch = curl_init();
    foreach ($_POST as $a => $b) {
        $post[htmlentities($a)]=htmlentities($b);
    }
    curl_setopt($ch, CURLOPT_URL,$url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($post));

    // receive server response ...
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $server_output = curl_exec ($ch);
    curl_close ($ch);

    echo $server_output;
}

?>

1

19 gennaio 2020 Certificato autofirmato FISSA:

Per riprodurre video, immagini, chiamare il servizio web per qualsiasi certificato autofirmato o connettersi a qualsiasi URL non protetto, basta chiamare questo metodo prima di eseguire qualsiasi azione, risolverà il problema relativo al problema del certificato:

CODICE KOTLIN

  private fun disableSSLCertificateChecking() {
        val hostnameVerifier = object: HostnameVerifier {
            override fun verify(s:String, sslSession: SSLSession):Boolean {
                return true
            }
        }
        val trustAllCerts = arrayOf<TrustManager>(object: X509TrustManager {
            override fun getAcceptedIssuers(): Array<X509Certificate> {
                TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
            }

            //val acceptedIssuers:Array<X509Certificate> = null
            @Throws(CertificateException::class)
            override fun checkClientTrusted(arg0:Array<X509Certificate>, arg1:String) {// Not implemented
            }
            @Throws(CertificateException::class)
            override fun checkServerTrusted(arg0:Array<X509Certificate>, arg1:String) {// Not implemented
            }
        })
        try
        {
            val sc = SSLContext.getInstance("TLS")
            sc.init(null, trustAllCerts, java.security.SecureRandom())
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory())
            HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier)
        }
        catch (e: KeyManagementException) {
            e.printStackTrace()
        }
        catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        }
    }

0

Forse questo sarà utile ... funziona su client Java usando certificati autofirmati (non c'è controllo del certificato). Fai attenzione e usalo solo per casi di sviluppo perché non è affatto sicuro !!

Come ignorare gli errori del certificato SSL in Apache HttpClient 4.0

Spero che funzioni su Android solo aggiungendo la libreria HttpClient ... buona fortuna !!


1
No, non funziona su Android poiché si basa su metodi
obsoleti

0

Questo è un problema derivante dalla mancanza del supporto SNI (Server Name Identification) inA, ndroid 2.x. Ho lottato con questo problema per una settimana fino a quando mi sono imbattuto nella seguente domanda, che non solo fornisce un buon background del problema, ma fornisce anche una soluzione funzionante ed efficace priva di eventuali falle di sicurezza.

Errore "Nessun certificato peer" in Android 2.3 ma NON in 4

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.