accepter les connexions HTTPS avec des certificats auto-signés

153

J'essaie d'établir des connexions HTTPS, en utilisant HttpClientlib, mais le problème est que, puisque le certificat n'est pas signé par une autorité de certification reconnue (CA) comme Verisign , GlobalSIgn , etc., répertoriée sur l'ensemble des certificats de confiance Android, Je continue à avoir javax.net.ssl.SSLException: Not trusted server certificate.

J'ai vu des solutions où vous acceptez simplement tous les certificats, mais que faire si je veux demander à l'utilisateur?

Je souhaite obtenir une boîte de dialogue similaire à celle du navigateur, laissant l'utilisateur décider de continuer ou non. Je souhaite de préférence utiliser le même magasin de certificats que le navigateur. Des idées?

Morten
la source
Cette solution acceptée a fonctionné pour moi- stackoverflow.com/questions/2642777/…
Venkatesh le

Réponses:

171

La première chose à faire est de définir le niveau de vérification. De tels niveaux ne sont pas tant:

  • ALLOW_ALL_HOSTNAME_VERIFIER
  • BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
  • STRICT_HOSTNAME_VERIFIER

Bien que la méthode setHostnameVerifier () soit obsolète pour la nouvelle bibliothèque apache, mais pour la version du SDK Android, c'est normal. Et donc nous prenons ALLOW_ALL_HOSTNAME_VERIFIERet le plaçons dans l'usine de méthodes SSLSocketFactory.setHostnameVerifier().

Ensuite, vous devez définir notre usine pour le protocole sur https. Pour ce faire, appelez simplement la SchemeRegistry.register()méthode.

Ensuite, vous devez créer un DefaultHttpClientavec SingleClientConnManager. Également dans le code ci-dessous, vous pouvez voir que par défaut, nous utiliserons également notre drapeau ( ALLOW_ALL_HOSTNAME_VERIFIER) par la méthodeHttpsURLConnection.setDefaultHostnameVerifier()

Le code ci-dessous fonctionne pour moi:

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);
Nikolay Moskvin
la source
6
Je ne peux malheureusement pas faire fonctionner ce code, j'obtiens toujours le "Certificat de serveur non approuvé". Dois-je définir des autorisations supplémentaires pour que cela fonctionne?
Juriy
1
Ce code n'accepte-t-il pas seulement tous les certificats? J'ai besoin d'un popup pour l'accepter.
Morten
3
J'utilise org.apache.http.conn.ssl.SSLSocketFactorypourquoi je veux utiliser javax.net.ssl.HttpsURLConnection??
Someone Somewhere
9
Pouvez-vous expliquer en quoi ce code est préférable à la désactivation complète de la vérification des certificats? Je ne suis pas familier avec l'API ssl d'Android, mais en un coup d'œil, cela semble totalement dangereux contre les attaquants actifs.
CodesInChaos
3
Je suggérerais d'utiliser ThreadSafeClientConnManager au lieu de SingleClientConnManager
Farm
124

Les étapes principales suivantes sont nécessaires pour établir une connexion sécurisée à partir des autorités de certification qui ne sont pas considérées comme approuvées par la plate-forme Android.

Comme demandé par de nombreux utilisateurs, j'ai reproduit les parties les plus importantes de mon article de blog ici:

  1. Récupérez tous les certificats requis (racine et toute autorité de certification intermédiaire)
  2. Créez un keystore avec keytool et le fournisseur BouncyCastle et importez les certificats
  3. Chargez le keystore dans votre application Android et utilisez-le pour les connexions sécurisées (je recommande d'utiliser Apache HttpClient au lieu du standard java.net.ssl.HttpsURLConnection(plus facile à comprendre, plus performant)

Prenez les certificats

Vous devez obtenir tous les certificats qui créent une chaîne à partir du certificat de point de terminaison jusqu'à la racine CA. Cela signifie, tous les certificats de l'autorité de certification intermédiaire (le cas échéant) ainsi que le certificat de l'autorité de certification racine. Vous n'avez pas besoin d'obtenir le certificat de point de terminaison.

Créer le keystore

Téléchargez le fournisseur BouncyCastle et stockez-le dans un emplacement connu. Assurez-vous également que vous pouvez appeler la commande keytool (généralement située sous le dossier bin de votre installation JRE).

Importez maintenant les certificats obtenus (n'importez pas le certificat de point de terminaison) dans un magasin de clés au format BouncyCastle.

Je ne l'ai pas testé, mais je pense que l'ordre d'importation des certificats est important. Cela signifie que vous importez d'abord le certificat de l'autorité de certification intermédiaire le plus bas, puis jusqu'au certificat de l'autorité de certification racine.

Avec la commande suivante, un nouveau keystore (s'il n'est pas déjà présent) avec le mot de passe mysecret sera créé et le certificat de CA intermédiaire sera importé. J'ai également défini le fournisseur BouncyCastle, où il peut être trouvé sur mon système de fichiers et le format de keystore. Exécutez cette commande pour chaque certificat de la chaîne.

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

Vérifiez si les certificats ont été correctement importés dans le fichier de clés:

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

Devrait afficher toute la chaîne:

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

Vous pouvez maintenant copier le keystore en tant que ressource brute dans votre application Android sous res/raw/

Utilisez le keystore dans votre application

Tout d'abord, nous devons créer un Apache HttpClient personnalisé qui utilise notre keystore pour les connexions 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);
        }
    }
}

Nous avons créé notre HttpClient personnalisé, maintenant nous pouvons l'utiliser pour des connexions sécurisées. Par exemple, lorsque nous faisons un appel GET à une ressource 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();

C'est tout ;)

saxos
la source
8
Ceci n'est utile que pour obtenir des certificats avant d'expédier votre application. N'aide pas vraiment les utilisateurs à accepter leurs propres certificats. pour votre application
Fuzzy
Salut à tous, quelqu'un peut-il me dire le processus de validation du keystore avec truststore pour l'implémentation ci-dessus ??? merci d'avance ..
andriod_testing
Cela a bien fonctionné ... mais maintenant je suis confronté à un problème lorsque je renouvelle le certificat sur le serveur. Il semble étrange que chaque fois que je mets à jour le certificat sur mon serveur, le magasin côté client devrait également être mis à jour. Il doit y avoir un meilleur moyen: |
bpn
Réponse de Gr8, je suggérerais d'utiliser ThreadSafeClientConnManager au lieu de SingleClientConnManager
Ferme
J'ai ajouté /res/raw/mykeystore.bks, bien que incapable de résoudre la référence à cela. comment résoudre ça?
uniruddh
16

Si vous disposez d'un certificat personnalisé / auto-signé sur le serveur qui n'est pas présent sur l'appareil, vous pouvez utiliser la classe ci-dessous pour le charger et l'utiliser côté client sous Android:

Placez le *.crtfichier de certificat /res/rawafin qu'il soit disponible à partir deR.raw.*

Utilisez la classe ci-dessous pour obtenir un HTTPClientou HttpsURLConnectionqui aura une fabrique de sockets utilisant ce certificat:

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

}

Points clés:

  1. Certificateles objets sont générés à partir de .crtfichiers.
  2. Une valeur par défaut KeyStoreest créée.
  3. keyStore.setCertificateEntry("ca", cert)ajoute un certificat au magasin de clés sous l'alias "ca". Vous modifiez le code pour ajouter plus de certificats (CA intermédiaire, etc.).
  4. L'objectif principal est de générer un SSLSocketFactoryqui peut ensuite être utilisé par HTTPClientou HttpsURLConnection.
  5. SSLSocketFactory peut être configuré davantage, par exemple pour ignorer la vérification du nom d'hôte, etc.

Plus d'informations sur: http://developer.android.com/training/articles/security-ssl.html

Dakota du Sud
la source
Où puis-je obtenir des .crtfichiers ou télécharger à partir d'un serveur?
zionpi
@zionpi Le fichier de certificat sera le même que celui utilisé par le serveur compatible TLS auquel vous vous connectez.
SD
Merci! C'était si simple!
kapil thadani
@SD Comment puis-je utiliser un fichier .P12 au lieu de .crt?
Rakesh R Nair
J'ai un doute similaire froid, s'il vous plaît, aidez stackoverflow.com/questions/57389622/…
StezPet
8

J'étais frustré d'essayer de connecter mon application Android à mon service RESTful en utilisant https. J'étais également un peu ennuyé par toutes les réponses suggérant de désactiver complètement la vérification des certificats. Si vous le faites, quel est l'intérêt de https?

Après avoir googlé le sujet pendant un moment, j'ai finalement trouvé cette solution où les jars externes ne sont pas nécessaires, juste les API Android. Merci à Andrew Smith, qui l'a publié en juillet 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;
    }
}

Cela a bien fonctionné pour mon application de maquette.

Gonzalo Fernández
la source
X509Certificate lequel dois-je importer java ou javax?
Siddharth
J'ai importéimport java.security.cert.X509Certificate;
Gonzalo Fernández
Merci pour cela. C'est vraiment du travail et simple
Anuradhe Dilshan
6

La meilleure réponse n'a pas fonctionné pour moi. Après quelques recherches, j'ai trouvé les informations requises sur "Android Developer": https://developer.android.com/training/articles/security-ssl.html#SelfSigned

La création d'une implémentation vide de X509TrustManager a fait l'affaire:

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

Veuillez noter que cette implémentation vide de TustManager n'est qu'un exemple et son utilisation dans un environnement productif entraînerait une grave menace pour la sécurité!

Markus Lenger
la source
1
juste fyi - idk si c'était comme ça à l'époque, mais ils semblent fortement décourager cette approche maintenant (voir la note)
Saik Caskey
6

Google recommande l'utilisation d' Android Volley pour les connexions HTTP / HTTPS , car cela HttpClientest obsolète. Donc, vous connaissez le bon choix :).

Et aussi, JAMAIS les certificats SSL NUKE (JAMAIS !!!).

Nuke SSL Certificates, est totalement contraire à l'objectif de SSL, qui est de promouvoir la sécurité . Il n'y a aucun sens d'utiliser SSL, si vous prévoyez de bombarder tous les certificats SSL qui viennent. Une meilleure solution serait de ne pas utiliser SSL, ou une meilleure solution serait de créer une personnalisation TrustManagersur votre application + en utilisant Android Volley pour les connexions HTTP / HTTPS.

Voici un Gist que j'ai créé, avec une LoginApp de base, effectuant des connexions HTTPS, en utilisant un certificat auto-signé côté serveur, accepté sur l'application.

Voici également un autre élément essentiel qui peut vous aider, pour créer des certificats SSL auto-signés pour la configuration sur votre serveur et également utiliser le certificat sur votre application. Très important: vous devez copier le fichier .crt qui a été généré par le script ci-dessus, dans le répertoire "raw" de votre projet Android.

Ivanleoncz
la source
Bonjour Ivan, je n'ai jamais travaillé avec des certificats SSL. Voudriez-vous élaborer un peu, comment puis-je obtenir le fichier .crt?
jlively
Salut Jively! Je vois. Oui bien sûr. Mais tout d'abord, pourriez-vous jeter un coup d'œil au deuxième élément essentiel que j'ai mentionné ci-dessus? J'ai mis deux fichiers sur ce Gist: l'un est le fichier utilisé par le script et l'autre est le script lui-même, qui utilise le binaire "openssl" afin de lire le fichier et ensuite, construire le fichier qui contient le certificat SSL ( .crt). Faites-moi savoir si vous avez réussi à tout comprendre. Cordialement :).
ivanleoncz
Hmm oui, j'ai regardé ces 2 éléments essentiels, mais je ne comprends pas vraiment comment les utiliser?
jlively
4

Voici comment vous pouvez ajouter des certificats supplémentaires à votre KeyStore pour éviter ce problème: Approuver tous les certificats à l'aide de HttpClient sur HTTPS

Cela n'invitera pas l'utilisateur comme vous le demandez, mais cela réduira la probabilité que l'utilisateur rencontre une erreur "Certificat de serveur non approuvé".

emmby
la source
Juste à des fins de test, vous ne pouvez pas publier une application dans le Play Store avec cette astuce car elle sera rejetée
ariel
3

Le moyen le plus simple de créer un certificat SSL

Ouvrez Firefox (je suppose que c'est également possible avec Chrome, mais c'est plus facile pour moi avec FF)

Visitez votre site de développement avec un certificat SSL auto-signé.

Cliquez sur le certificat (à côté du nom du site)

Cliquez sur "Plus d'informations"

Cliquez sur "Afficher le certificat"

Cliquez sur "Détails"

Cliquez sur "Exporter ..."

Choisissez "Certificat X.509 avec chaîne (PEM)", sélectionnez le dossier et le nom pour l'enregistrer et cliquez sur "Enregistrer"

Accédez à la ligne de commande, dans le répertoire où vous avez téléchargé le fichier pem et exécutez "openssl x509 -inform PEM -outform DM -in .pem -out .crt"

Copiez le fichier .crt à la racine du dossier / sdcard dans votre appareil Android À l'intérieur de votre appareil Android, Paramètres> Sécurité> Installer à partir du stockage.

Il doit détecter le certificat et vous permettre de l'ajouter à l'appareil Accédez à votre site de développement.

La première fois, il devrait vous demander de confirmer l'exception de sécurité. C'est tout.

Le certificat doit fonctionner avec n'importe quel navigateur installé sur votre Android (Navigateur, Chrome, Opera, Dolphin ...)

N'oubliez pas que si vous diffusez vos fichiers statiques à partir d'un domaine différent (nous sommes tous des putes à vitesse de page), vous devez également ajouter le certificat pour ce domaine.

Mani Kandan
la source
2

J'ai écrit une petite bibliothèque ssl-utils-android pour faire confiance à un certificat particulier sur Android.

Vous pouvez simplement charger n'importe quel certificat en donnant le nom de fichier à partir du répertoire des ressources.

Usage:

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

Aucun de ces correctifs n'a fonctionné pour ma plate-forme de développement ciblant le SDK 16, version 4.1.2, j'ai donc trouvé une solution de contournement.

Mon application stocke les données sur le serveur en utilisant " http://www.example.com/page.php?data=somedata "

Récemment, page.php a été déplacé vers " https://www.secure-example.com/page.php " et je continue à recevoir "javax.net.ssl.SSLException: certificat de serveur non approuvé".

Au lieu d'accepter tous les certificats pour une seule page, en commençant par ce guide, j'ai résolu mon problème en écrivant ma propre page.php publiée sur " 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;
}

?>
Rudy
la source
1

19 janvier 2020 PROBLÈME D'ÉMISSION DU Certificat auto-signé:

Pour lire une vidéo, une image, appeler le service Web pour tout certificat auto-signé ou vous connecter à une URL non sécurisée, appelez simplement cette méthode avant d'effectuer toute action, cela résoudra votre problème concernant le problème du certificat:

CODE 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()
        }
    }
Shobhakar Tiwari
la source
0

Peut-être que cela sera utile ... cela fonctionne sur les clients java utilisant des certificats auto-signés (il n'y a pas de vérification du certificat). Soyez prudent et utilisez-le uniquement pour les cas de développement car ce n'est pas du tout sécurisé !!

Comment ignorer les erreurs de certificat SSL dans Apache HttpClient 4.0

J'espère que cela fonctionnera sur Android en ajoutant simplement la bibliothèque HttpClient ... bonne chance !!

EmP
la source
1
Non, cela ne fonctionne pas sur Android car il repose sur des méthodes obsolètes qui ne sont pas présentes dans la variante Android :-(
kellyfj
0

Il s'agit d'un problème résultant d'un manque de prise en charge de SNI (Server Name Identification) dansA, ndroid 2.x. Je luttais avec ce problème pendant une semaine jusqu'à ce que je tombe sur la question suivante, qui non seulement donne un bon aperçu du problème, mais fournit également une solution fonctionnelle et efficace dépourvue de toute faille de sécurité.

Erreur `` Pas de certificat de pair '' dans Android 2.3 mais PAS dans 4

alumat
la source