Kürzlich wurde eine Frage zu den HttpClient
über Https gestellt ( hier zu finden ). Ich habe einige Fortschritte gemacht, bin aber auf neue Probleme gestoßen. Wie bei meinem letzten Problem kann ich anscheinend nirgendwo ein Beispiel finden, das für mich funktioniert. Grundsätzlich möchte ich, dass mein Client jedes Zertifikat akzeptiert (weil ich immer nur auf einen Server zeige), aber ich bekomme immer einjavax.net.ssl.SSLException: Not trusted server certificate exception.
Das habe ich also:
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);
}
Und hier ist der Fehler, den ich bekomme:
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
java
ssl
https
certificate
apache-httpclient-4.x
Harrisonlee
quelle
quelle
Antworten:
Hinweis: Implementieren Sie dies nicht in Produktionscode, den Sie jemals in einem Netzwerk verwenden werden, dem Sie nicht vollständig vertrauen. Besonders alles, was über das öffentliche Internet geht.
Ihre Frage ist genau das, was ich wissen möchte. Nachdem ich einige Suchen durchgeführt habe, ist die Schlussfolgerung wie folgt.
Auf HttpClient-Weise sollten Sie eine benutzerdefinierte Klasse aus org.apache.http.conn.ssl.SSLSocketFactory erstellen, nicht aus der org.apache.http.conn.ssl.SSLSocketFactory selbst. Einige Hinweise finden Sie in diesem Beitrag. Die benutzerdefinierte SSL-Verarbeitung funktioniert unter Android 2.2 FroYo nicht mehr .
Ein Beispiel ist wie ...
und verwenden Sie diese Klasse beim Erstellen einer Instanz von HttpClient.
Übrigens, der Link unten ist für jemanden, der nach einer HttpURLConnection-Lösung sucht. HTTP-Verbindung Android
Ich habe die beiden oben genannten Arten von Lösungen auf froyo getestet und sie funktionieren in meinen Fällen alle wie ein Zauber. Schließlich kann die Verwendung von HttpURLConnection zu Umleitungsproblemen führen, die jedoch über das Thema hinausgehen.
Hinweis: Bevor Sie sich entscheiden, allen Zertifikaten zu vertrauen, sollten Sie die Site wahrscheinlich genau kennen und für den Endbenutzer nicht schädlich sein.
In der Tat sollte das Risiko, das Sie eingehen, sorgfältig abgewogen werden, einschließlich der Auswirkungen der Hacker-Mock-Site, die in den folgenden Kommentaren erwähnt wird, die ich zutiefst schätze. In einigen Situationen, obwohl es schwierig sein kann, sich um alle Zertifikate zu kümmern, sollten Sie die impliziten Nachteile besser kennen, um allen zu vertrauen.
quelle
getAcceptedIssuers()
darf nicht null zurückgeben.Grundsätzlich haben Sie vier mögliche Lösungen, um eine "Nicht vertrauenswürdige" Ausnahme unter Android mithilfe von httpclient zu beheben:
Diese Antwort verwendet die Lösung Nr. 4, die mir am robustesten erscheint.
Die Lösung besteht darin, eine SSLSocketFactory zu verwenden, die mehrere KeyStores akzeptieren kann, sodass Sie Ihren eigenen KeyStore mit Ihren eigenen Zertifikaten versorgen können. Auf diese Weise können Sie zusätzliche Zertifikate der obersten Ebene wie Thawte laden, die auf einigen Android-Geräten möglicherweise fehlen. Außerdem können Sie Ihre eigenen selbstsignierten Zertifikate laden. Es werden zuerst die integrierten Standardgerätezertifikate verwendet und nur bei Bedarf auf Ihre zusätzlichen Zertifikate zurückgegriffen.
Zunächst möchten Sie feststellen, welches Zertifikat in Ihrem KeyStore fehlt. Führen Sie den folgenden Befehl aus:
Und Sie sehen die Ausgabe wie folgt:
Wie Sie sehen, stammt unser Stammzertifikat von Thawte. Gehen Sie zur Website Ihres Anbieters und suchen Sie das entsprechende Zertifikat. Für uns war es hier und Sie können sehen, dass das, was wir brauchten, das Copyright 2006 war.
Wenn Sie ein selbstsigniertes Zertifikat verwenden, mussten Sie den vorherigen Schritt nicht ausführen, da Sie bereits über Ihr Signaturzertifikat verfügen.
Erstellen Sie dann eine Keystore-Datei mit dem fehlenden Signaturzertifikat. Crazybob hat Details dazu auf Android , aber die Idee ist, Folgendes zu tun:
Wenn Sie es noch nicht haben, laden Sie die Bouncy Castle Provider-Bibliothek von folgender Adresse herunter: http://www.bouncycastle.org/latest_releases.html . Dies wird auf Ihrem Klassenpfad unten gehen.
Führen Sie einen Befehl aus, um das Zertifikat vom Server zu extrahieren und eine PEM-Datei zu erstellen. In diesem Fall mycert.pem.
Führen Sie dann die folgenden Befehle aus, um den Schlüsselspeicher zu erstellen.
Sie werden feststellen, dass das obige Skript das Ergebnis in platziert
res/raw/mystore.bks
. Jetzt haben Sie eine Datei, die Sie in Ihre Android-App laden und die fehlenden Zertifikate bereitstellen.Registrieren Sie dazu Ihre SSLSocketFactory für das SSL-Schema:
So erstellen Sie Ihre SSLSocketFactory:
Und schließlich der AdditionalKeyStoresSSLSocketFactory-Code, der Ihren neuen KeyStore akzeptiert und prüft, ob der integrierte KeyStore ein SSL-Zertifikat nicht validieren kann:
quelle
http://stackoverflow.com/questions/7822381/need-help-understanding-certificate-chains
Fügen Sie diesen Code vor dem hinzu
HttpsURLConnection
und es wird getan. Ich habe es bekommen.Ich hoffe das hilft dir.
quelle
Das ist eine schlechte Idee. Das Vertrauen in ein Zertifikat ist nur (sehr) geringfügig besser als die Verwendung von überhaupt keinem SSL. Wenn Sie sagen "Ich möchte, dass mein Client ein Zertifikat akzeptiert (weil ich immer nur auf einen Server zeige)", gehen Sie davon aus, dass das Zeigen auf "einen Server" sicher ist, was nicht in einem öffentlichen Netzwerk der Fall ist.
Sie sind völlig offen für einen Man-in-the-Middle-Angriff, indem Sie einem Zertifikat vertrauen. Jeder kann Ihre Verbindung vertreten, indem er eine separate SSL-Verbindung mit Ihnen und dem Endserver herstellt. Das MITM hat dann Zugriff auf Ihre gesamte Anfrage und Antwort. Sofern Sie SSL überhaupt nicht benötigt haben (Ihre Nachricht ist nicht vertraulich und führt keine Authentifizierung durch), sollten Sie nicht allen Zertifikaten blind vertrauen.
Sie sollten in Betracht ziehen, das öffentliche Zertifikat mithilfe von Keytool zu einem JKS hinzuzufügen und dieses zum Erstellen Ihrer Socket-Factory zu verwenden, z.
Dies hat eine Einschränkung zu beachten. Das Zertifikat läuft irgendwann ab und der Code funktioniert zu diesem Zeitpunkt nicht mehr. Sie können leicht feststellen, wann dies geschehen wird, indem Sie sich das Zertifikat ansehen.
quelle
null
inSSLContext.init). You should also use the default algorithms (KMF/TMF.getDefaultAlgorithm() ), instead of hard-coding
SunX509 verwenden` (mehr noch, da der Standard für TMF tatsächlichPKIX
auf der Sun / Oracle-JVM liegt).myjks.jks
kommt das?Sie können die HttpURLConnection-SSL-Prüfung zu Testzwecken auf diese Weise deaktivieren, da API 8:
quelle
org.apache.http.conn.ssl.AllowAllHostnameVerifier
ist veraltet.AllowAllHostnameVerifier
wird ersetzt durchNoopHostnameVerifier
"Die API von HttpComponents wurde geändert. Es funktioniert mit dem folgenden Code.
quelle
Der obige Code unter https://stackoverflow.com/a/6378872/1553004 ist korrekt, außer dass er auch den Hostnamen-Verifizierer aufrufen muss:
Ich habe mich ausdrücklich bei stackoverflow angemeldet, um dieses Update hinzuzufügen. Beachten Sie meine Warnung!
quelle
Ich füge eine Antwort für diejenigen hinzu, die httpclient-4.5 verwenden, und funktioniert wahrscheinlich auch für 4.4.
quelle
Das Vertrauen in alle Zertifikate war für mich keine echte Alternative. Daher habe ich Folgendes getan, um HttpsURLConnection dazu zu bringen, einem neuen Zertifikat zu vertrauen (siehe auch http://nelenkov.blogspot.jp/2011/12/using-custom-certificate-trust-store- on.html ).
Holen Sie sich das Zertifikat; Dazu habe ich das Zertifikat in Firefox exportiert (auf das kleine Schlosssymbol klicken, Zertifikatdetails abrufen, auf Exportieren klicken) und dann mit portecle einen Truststore (BKS) exportiert.
Laden Sie den Truststore aus /res/raw/geotrust_cert.bks mit dem folgenden Code:
quelle
IOExceptionjavax.net.ssl.SSLPeerUnverifiedException: No peer certificate
. Dies, wenn der eigentliche Ausführungsaufruf auf dem HttpClient ausgeführt wird, nachdem das obige Setup durchgeführt wurde.Hier ist eine sehr einfache Version mit 4.1.2 httpclient-Code. Dies kann dann an einen beliebigen Vertrauensalgorithmus angepasst werden, den Sie für richtig halten.
quelle
Ich habe eine Antwort von "emmby" (beantwortet am 16. Juni 11 um 21:29 Uhr), Punkt 4: "Erstellen Sie eine benutzerdefinierte SSLSocketFactory, die das integrierte Zertifikat KeyStore verwendet, aber für alles, was fehlschlägt, auf einen alternativen KeyStore zurückgreift mit der Standardeinstellung zu überprüfen. "
Dies ist eine vereinfachte Implementierung. Laden Sie den Systemschlüsselspeicher und führen Sie ihn mit dem Anwendungsschlüsselspeicher zusammen.
Ein einfacher Modus zum Konvertieren von JKS in BKS:
* Hinweis: In Android 4.0 (ICS) hat sich der Trust Store geändert. Weitere Informationen: http://nelenkov.blogspot.com.es/2011/12/ics-trust-store-implementation.html
quelle
Gehen Sie folgendermaßen vor, wenn Sie möchten, dass alle Zertifikate (zu Testzwecken) über OAuth funktionieren:
1) Laden Sie hier den Quellcode der Android OAuth API herunter: https://github.com/kaeppler/signpost
2) Suchen Sie die Klasse "CommonsHttpOAuthProvider"
3) Ändern Sie es wie folgt:
Die obige "MySSLSocketFactory" basiert auf der akzeptierten Antwort. Um es noch einfacher zu machen, folgt hier die komplette Klasse:
}}
Hoffe das hilft jemandem.
quelle
HttpClient
und HTTPS; nicht OAuth für Android aus einem GitHub-Projekt.Ich habe dies verwendet und es funktioniert für mich auf allen Betriebssystemen.
quelle
Nur das Hinzufügen
-Dtrust_all_cert=true
zu VM-Argumenten sollte ausreichen. Dieses Argument weist Java an, Zertifikatprüfungen zu ignorieren.quelle
Jeder Körper, der immer noch mit StartCom SSL-Zertifikaten unter Android 2.1 zu kämpfen hat, besucht https://www.startssl.com/certs/ und lädt das ca.pem herunter, jetzt in der Antwort von @emmby replace
mit
Sollte sofort funktionieren. Ich hatte über einen Tag lang Probleme, selbst nach einer perfekten Antwort von @emmby . Ich hoffe, das hilft jemandem ...
quelle
Verwenden Sie diese Klasse
}}
quelle
Geben Sie hier die Bildbeschreibung ein
Ein sspi ist in xamarin android fehlgeschlagen.
Ich habe diese Lösung gefunden; Fügen Sie diesen Code ein, bevor Sie auf einen HTTPS-Link klicken
quelle
arbeite mit allen https
quelle
Es gibt viele Antworten oben, aber ich konnte keine davon richtig zum Laufen bringen (mit meiner begrenzten Zeit). Für alle anderen in der gleichen Situation können Sie den folgenden Code ausprobieren, der für meine Java-Testzwecke perfekt funktioniert hat:
und rufe an wie:
Referenz: http://tech.chitgoks.com/2011/04/24/how-to-avoid-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-problem-using-apache-httpclient/
quelle
Verwenden Sie einfach diese -
quelle
Daniels Antwort war gut, außer dass ich diesen Code ändern musste ...
zu diesem Code ...
um es zum Laufen zu bringen.
quelle