Akzeptieren von HTTPS-Verbindungen mit selbstsignierten Zertifikaten


153

Ich versuche, HTTPS-Verbindungen mit HttpClientlib herzustellen, aber das Problem ist, dass das Zertifikat nicht von einer anerkannten Zertifizierungsstelle ( Verisign , GlobalSIgn usw. ) signiert ist, die im Satz der vertrauenswürdigen Android-Zertifikate aufgeführt ist. Ich bekomme immer javax.net.ssl.SSLException: Not trusted server certificate.

Ich habe Lösungen gesehen, bei denen Sie einfach alle Zertifikate akzeptieren, aber was ist, wenn ich den Benutzer fragen möchte?

Ich möchte einen Dialog ähnlich dem des Browsers erhalten, in dem der Benutzer entscheiden kann, ob er fortfahren möchte oder nicht. Am liebsten möchte ich den gleichen Zertifikatsspeicher wie den Browser verwenden. Irgendwelche Ideen?


Diese akzeptierte Lösung funktionierte für me- stackoverflow.com/questions/2642777/…
Venkatesh

Antworten:


171

Als erstes müssen Sie die Überprüfungsstufe festlegen. Solche Ebenen sind nicht so sehr:

  • ALLOW_ALL_HOSTNAME_VERIFIER
  • BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
  • STRICT_HOSTNAME_VERIFIER

Die Methode setHostnameVerifier () ist zwar für neue Bibliothek Apache veraltet, aber für die Version im Android SDK ist normal. Und so nehmen ALLOW_ALL_HOSTNAME_VERIFIERund setzen wir es in der Methodenfabrik SSLSocketFactory.setHostnameVerifier().

Als nächstes müssen Sie unsere Factory für das Protokoll auf https einstellen. Rufen Sie dazu einfach die SchemeRegistry.register()Methode auf.

Dann müssen Sie ein DefaultHttpClientmit erstellen SingleClientConnManager. Auch im folgenden Code können Sie sehen, dass standardmäßig auch unser flag ( ALLOW_ALL_HOSTNAME_VERIFIER) von der Methode verwendet wirdHttpsURLConnection.setDefaultHostnameVerifier()

Der folgende Code funktioniert für mich:

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
Ich kann diesen Code leider nicht zum Laufen bringen, ich erhalte immer noch das "Nicht vertrauenswürdige Serverzertifikat". Gibt es zusätzliche Berechtigungen, die ich festlegen muss, damit es funktioniert?
Juriy

1
Akzeptiert dieser Code nicht einfach alle Zertifikate? Ich brauche ein Popup, um es zu akzeptieren.
Morten

3
Ich benutze org.apache.http.conn.ssl.SSLSocketFactorywarum will ich verwenden javax.net.ssl.HttpsURLConnection?
Jemand irgendwo

9
Können Sie erklären, wie dieser Code besser ist, als die Zertifikatsüberprüfung vollständig zu deaktivieren? Ich bin nicht mit der SSL-API von Android vertraut, aber auf den ersten Blick scheint dies gegenüber aktiven Angreifern völlig unsicher zu sein.
CodesInChaos

3
Ich würde vorschlagen, ThreadSafeClientConnManager anstelle von SingleClientConnManager
Farm

124

Die folgenden Hauptschritte sind erforderlich, um eine gesicherte Verbindung von Zertifizierungsstellen herzustellen, die von der Android-Plattform nicht als vertrauenswürdig eingestuft werden.

Wie von vielen Benutzern gewünscht, habe ich die wichtigsten Teile meines Blog-Artikels hier gespiegelt :

  1. Besorgen Sie sich alle erforderlichen Zertifikate (Root- und Zwischenzertifizierungsstellen).
  2. Erstellen Sie einen Keystore mit Keytool und dem BouncyCastle- Anbieter und importieren Sie die Zertifikate
  3. Laden Sie den Keystore in Ihre Android-App und verwenden Sie ihn für die gesicherten Verbindungen (ich empfehle, den Apache HttpClient anstelle des Standards zu verwenden java.net.ssl.HttpsURLConnection(einfacher zu verstehen, leistungsfähiger).

Schnapp dir die Zertifikate

Sie müssen alle Zertifikate, die eine Kette bilden, vom Endpunktzertifikat bis zur Stammzertifizierungsstelle erhalten. Dies bedeutet, dass alle (falls vorhanden) Zwischenzertifizierungsstellenzertifikate sowie das Stammzertifizierungsstellenzertifikat vorhanden sind. Sie müssen das Endpunktzertifikat nicht erhalten.

Erstellen Sie den Keystore

Laden Sie den BouncyCastle-Anbieter herunter und speichern Sie ihn an einem bekannten Ort. Stellen Sie außerdem sicher, dass Sie den Befehl keytool aufrufen können (normalerweise im Ordner bin Ihrer JRE-Installation).

Importieren Sie nun die erhaltenen Zertifikate (importieren Sie das Endpunktzertifikat nicht) in einen BouncyCastle-formatierten Keystore.

Ich habe es nicht getestet, aber ich denke, die Reihenfolge des Imports der Zertifikate ist wichtig. Dies bedeutet, dass Sie zuerst das unterste Zwischenzertifizierungsstellenzertifikat und dann bis zum Stammzertifizierungsstellenzertifikat importieren.

Mit dem folgenden Befehl wird ein neuer Schlüsselspeicher (falls nicht bereits vorhanden) mit dem Kennwort mysecret erstellt und das Zwischenzertifizierungsstellenzertifikat importiert. Ich habe auch den BouncyCastle-Anbieter definiert, der sich in meinem Dateisystem und im Keystore-Format befindet. Führen Sie diesen Befehl für jedes Zertifikat in der Kette aus.

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

Überprüfen Sie, ob die Zertifikate korrekt in den Keystore importiert wurden:

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

Sollte die gesamte Kette ausgeben:

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

Jetzt können Sie den Keystore als Rohstoff in Ihre Android-App unter kopieren res/raw/

Verwenden Sie den Keystore in Ihrer App

Zunächst müssen wir einen benutzerdefinierten Apache HttpClient erstellen, der unseren Keystore für HTTPS-Verbindungen verwendet:

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

Wir haben unseren benutzerdefinierten HttpClient erstellt und können ihn jetzt für sichere Verbindungen verwenden. Zum Beispiel, wenn wir eine REST-Ressource mit GET aufrufen:

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

Das ist es ;)


8
Dies ist nur nützlich, um Zertifikate zu erhalten, bevor Sie Ihre Bewerbung versenden. Hilft Benutzern nicht wirklich, ihre eigenen Zertifikate zu akzeptieren. für Ihre Anwendung
Fuzzy

Hallo zusammen, kann mir jemand den Validierungsprozess für den Keystore mit Truststore für die obige Implementierung mitteilen?
Vielen

Dies hat gut funktioniert. Aber jetzt habe ich ein Problem, wenn ich das Zertifikat auf dem Server erneut verschlüssle. Es scheint seltsam, dass jedes Mal, wenn ich das Zertifikat auf meinem Server aktualisiere, auch der clientseitige Speicher aktualisiert werden sollte. Es muss einen besseren Weg geben: |
Bpn

Gr8 Antwort, ich würde vorschlagen, ThreadSafeClientConnManager anstelle von SingleClientConnManager
Farm

Ich habe hinzugefügt /res/raw/mykeystore.bks, obwohl ich den Verweis darauf nicht auflösen kann. wie kann man das lösen?
Uniruddh

16

Wenn Sie ein benutzerdefiniertes / selbstsigniertes Zertifikat auf dem Server haben, das nicht auf dem Gerät vorhanden ist, können Sie es mit der folgenden Klasse laden und auf der Clientseite in Android verwenden:

Legen Sie das Zertifikat - *.crtDatei in /res/rawso dass es verfügbar ist vonR.raw.*

Verwenden Sie die folgende Klasse, um eine HTTPClientoder HttpsURLConnectioneine Socket-Fabrik zu erhalten, die dieses Zertifikat verwendet:

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

}

Wichtige Punkte:

  1. Certificate Objekte werden generiert aus .crt Dateien .
  2. Ein Standard KeyStorewird erstellt.
  3. keyStore.setCertificateEntry("ca", cert)fügt dem Schlüsselspeicher unter dem Alias ​​"ca" ein Zertifikat hinzu. Sie ändern den Code, um weitere Zertifikate hinzuzufügen (Zwischenzertifizierungsstelle usw.).
  4. Hauptziel ist es, ein zu generieren, SSLSocketFactorydas dann von HTTPClientoder verwendet werden kann HttpsURLConnection.
  5. SSLSocketFactory kann weiter konfiguriert werden, um beispielsweise die Überprüfung des Hostnamens zu überspringen usw.

Weitere Informationen unter: http://developer.android.com/training/articles/security-ssl.html


Wo kann ich .crtDateien herunterladen? Von einem Server herunterladen?
Zionpi

@zionpi Die Zertifikatdatei wird von dem TLS-fähigen Server verwendet, zu dem Sie eine Verbindung herstellen.
SD

Vielen Dank! Das war so einfach!
Kapil Thadani

@SD Wie kann ich die .P12-Datei anstelle der .crt-Datei verwenden?
Rakesh R Nair

Ich habe einen ähnlichen Zweifel kalt Sie bitte helfen stackoverflow.com/questions/57389622/…
StezPet

8

Ich war frustriert, als ich versuchte, meine Android-App über https mit meinem RESTful-Dienst zu verbinden. Außerdem war ich etwas verärgert über all die Antworten, die darauf hinwiesen, die Zertifikatsprüfung insgesamt zu deaktivieren. Wenn Sie dies tun, worum geht es bei https?

Nachdem ich eine Weile über das Thema gegoogelt hatte, fand ich endlich diese Lösung, bei der keine externen Gläser benötigt werden, sondern nur Android-APIs. Vielen Dank an Andrew Smith, der es im Juli 2014 gepostet hat

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

Es hat gut funktioniert für meine Modell-App.


X509Zertifikat welches sollte ich Java oder Javax importieren?
Siddharth

Ich importierteimport java.security.cert.X509Certificate;
Gonzalo Fernández

Vielen Dank dafür. Es ist wirklich Arbeit und einfach
Anuradhe Dilshan

6

Die Top-Antwort hat bei mir nicht funktioniert. Nach einigen Nachforschungen fand ich die erforderlichen Informationen zu "Android Developer": https://developer.android.com/training/articles/security-ssl.html#SelfSigned

Das Erstellen einer leeren Implementierung von X509TrustManager hat den Trick gemacht:

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

Bitte beachten Sie, dass diese leere Implementierung von TustManager nur ein Beispiel ist und die Verwendung in einer produktiven Umgebung eine ernsthafte Sicherheitsbedrohung darstellen würde!


1
Nur zu Ihrer Information, wenn es damals so war, aber sie scheinen diesen Ansatz jetzt stark zu entmutigen (siehe Anmerkung)
Saik Caskey

6

Google empfiehlt die Verwendung von Android Volley für HTTP / HTTPS-Verbindungen , da dies HttpClientveraltet ist. Sie kennen also die richtige Wahl :).

Und NIE NUKE SSL-Zertifikate (NIE !!!).

SSL-Zertifikate zu zerstören, ist völlig gegen den Zweck von SSL, das die Sicherheit fördert . Es macht keinen Sinn, SSL zu verwenden, wenn Sie alle kommenden SSL-Zertifikate bombardieren möchten. Eine bessere Lösung wäre, kein SSL zu verwenden, oder eine bessere Lösung wäre das Erstellen einer benutzerdefinierten LösungTrustManager mit Android Volley für HTTP / HTTPS-Verbindungen für Ihre App + .

Hier ist ein Gist , die ich erstellt, mit einer grundlegenden LoginApp, HTTPS - Verbindungen durchgeführt wird , ein selbstsigniertes Zertifikat auf der Server-Seite verwenden, auf dem App akzeptiert.

Hier ist auch eine weitere Übersicht , die hilfreich sein kann, um selbstsignierte SSL-Zertifikate zum Einrichten auf Ihrem Server und zum Verwenden des Zertifikats in Ihrer App zu erstellen. Sehr wichtig: Sie müssen die vom obigen Skript generierte CRT-Datei aus Ihrem Android-Projekt in das Verzeichnis "raw" kopieren.


Hallo Ivan, ich habe noch nie mit SSL-Zertifikaten gearbeitet. Möchten Sie etwas näher darauf eingehen, wie erhalte ich die CRT-Datei?
lebhaft

Hallo Jively! Aha. Ja natürlich. Aber würde es Ihnen zuerst etwas ausmachen, einen Blick auf den zweiten Kern zu werfen, den ich oben erwähnt habe? Ich habe zwei Dateien in diese Liste eingefügt: Eine ist die vom Skript verwendete Datei und die andere ist das Skript selbst, das die Binärdatei "openssl" verwendet, um die Datei zu lesen und dann die Datei zu erstellen, die das SSL-Zertifikat enthält ( .crt). Lassen Sie mich wissen, ob Sie das Ganze verstanden haben. Grüße :).
ivanleoncz

Hmm ja, ich habe mir diese 2 Kernpunkte angesehen, aber ich kann nicht wirklich verstehen, wie ich sie benutze?
lebhaft

4

So können Sie Ihrem KeyStore zusätzliche Zertifikate hinzufügen, um dieses Problem zu vermeiden: Vertrauen aller Zertifikate mit HttpClient über HTTPS

Es wird den Benutzer nicht wie gewünscht dazu auffordern, aber es wird weniger wahrscheinlich, dass dem Benutzer der Fehler "Nicht vertrauenswürdiges Serverzertifikat" angezeigt wird.


Nur zu Testzwecken können Sie eine App mit diesem Trick nicht im Play Store veröffentlichen, da sie abgelehnt wird
ariel

3

Einfachste Möglichkeit zum Erstellen eines SSL-Zertifikats

Open Firefox (ich nehme an, es ist auch mit Chrome möglich, aber mit FF ist es für mich einfacher)

Besuchen Sie Ihre Entwicklungssite mit einem selbstsignierten SSL-Zertifikat.

Klicken Sie auf das Zertifikat (neben dem Site-Namen).

Klicken Sie auf "Weitere Informationen"

Klicken Sie auf "Zertifikat anzeigen"

Klicken Sie auf "Details"

Klicken Sie auf "Exportieren ..."

Wählen Sie "X.509-Zertifikat mit Kette (PEM)", wählen Sie den Ordner und den Namen aus, um es zu speichern, und klicken Sie auf "Speichern".

Gehen Sie zur Befehlszeile in das Verzeichnis, in das Sie die PEM-Datei heruntergeladen haben, und führen Sie "openssl x509 -inform PEM -outform DM -in .pem -out .crt" aus.

Kopieren Sie die CRT-Datei in das Stammverzeichnis des Ordners / sdcard auf Ihrem Android-Gerät. Wählen Sie auf Ihrem Android-Gerät Einstellungen> Sicherheit> Vom Speicher installieren.

Das Zertifikat sollte erkannt werden, und Sie können es dem Gerät hinzufügen. Navigieren Sie zu Ihrer Entwicklungssite.

Beim ersten Mal sollten Sie aufgefordert werden, die Sicherheitsausnahme zu bestätigen. Das ist alles.

Das Zertifikat sollte mit jedem auf Ihrem Android installierten Browser funktionieren (Browser, Chrome, Opera, Dolphin ...).

Denken Sie daran, dass Sie das Zertifikat für diese Domäne hinzufügen müssen, wenn Sie Ihre statischen Dateien von einer anderen Domäne aus bereitstellen (wir sind alle Hündinnen mit Seitengeschwindigkeit).


2

Ich schrieb kleine Bibliothek ssl-utils-android um einem bestimmten Zertifikat auf Android zu vertrauen.

Sie können einfach jedes Zertifikat laden, indem Sie den Dateinamen aus dem Assets-Verzeichnis angeben.

Verwendung:

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

1

Keines dieser Fixes funktionierte für meine Entwicklungsplattform für SDK 16, Release 4.1.2. Daher habe ich eine Problemumgehung gefunden.

Meine App speichert Daten auf dem Server unter Verwendung von " http://www.example.com/page.php?data=somedata ".

Kürzlich wurde page.php nach " https://www.secure-example.com/page.php " verschoben und ich erhalte weiterhin "javax.net.ssl.SSLException: Nicht vertrauenswürdiges Serverzertifikat".

Anstatt alle Zertifikate für nur eine Seite zu akzeptieren, löste ich mit diesem Handbuch mein Problem beim Schreiben meiner eigenen page.php, die auf " http://www.example.com/page.php " veröffentlicht wurde.

<?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. Januar 2020 Selbstsigniertes Zertifikat AUSGABE FIX:

Um Videos, Bilder abzuspielen, den Webservice für ein selbstsigniertes Zertifikat aufzurufen oder eine Verbindung zu einer ungesicherten URL herzustellen, rufen Sie einfach diese Methode auf, bevor Sie eine Aktion ausführen. Dadurch wird Ihr Problem bezüglich des Zertifikatproblems behoben:

KOTLIN CODE

  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

Vielleicht ist dies hilfreich ... es funktioniert auf Java-Clients, die selbstsignierte Zertifikate verwenden (das Zertifikat wird nicht überprüft). Seien Sie vorsichtig und verwenden Sie es nur für Entwicklungsfälle, da dies überhaupt nicht sicher ist !!

So ignorieren Sie SSL-Zertifikatfehler in Apache HttpClient 4.0

Hoffe, es wird auf Android funktionieren, wenn Sie nur die HttpClient-Bibliothek hinzufügen ... viel Glück!


1
Nein, es funktioniert nicht auf Android, da es auf veralteten Methoden basiert, die in der Android-Variante nicht vorhanden sind :-(
kellyfj

0

Dies ist ein Problem, das auf mangelnde SNI-Unterstützung (Server Name Identification) in A, ndroid 2.x zurückzuführen ist. Ich hatte eine Woche lang mit diesem Problem zu kämpfen, bis ich auf die folgende Frage stieß, die nicht nur einen guten Hintergrund des Problems bietet, sondern auch eine funktionierende und effektive Lösung ohne Sicherheitslücken bietet.

Fehler 'Kein Peer-Zertifikat' in Android 2.3, aber NICHT in 4

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.