Ich versuche, den folgenden Code in Android auszuführen
URLConnection l_connection = null;
// Create connection
uzip=new UnZipData(mContext);
l_url = new URL(serverurl);
if ("https".equals(l_url.getProtocol())) {
System.out.println("<<<<<<<<<<<<< Before TLS >>>>>>>>>>>>");
sslcontext = SSLContext.getInstance("TLS");
System.out.println("<<<<<<<<<<<<< After TLS >>>>>>>>>>>>");
sslcontext.init(null,
new TrustManager[] { new CustomTrustManager()},
new java.security.SecureRandom());
HttpsURLConnection
.setDefaultHostnameVerifier(new CustomHostnameVerifier());
HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext
.getSocketFactory());
l_connection = (HttpsURLConnection) l_url.openConnection();
((HttpsURLConnection) l_connection).setRequestMethod("POST");
} else {
l_connection = (HttpURLConnection) l_url.openConnection();
((HttpURLConnection) l_connection).setRequestMethod("POST");
}
/*System.setProperty("http.agent", "Android_Phone");*/
l_connection.setConnectTimeout(10000);
l_connection.setRequestProperty("Content-Language", "en-US");
l_connection.setUseCaches(false);
l_connection.setDoInput(true);
l_connection.setDoOutput(true);
System.out.println("<<<<<<<<<<<<< Before Connection >>>>>>>>>>>>");
l_connection.connect();
Ein l_connection.connect()
, es gibt diese SSLhandshakeException. Manchmal funktioniert es, aber meistens gibt es die Ausnahme. Es passiert nur auf Android 4.0 Emulator. Ich habe es auf Android 4.4 und 5.0 getestet, es funktioniert gut. Was könnte die Ursache dafür sein? Bitte helfen Sie
STACKTRACE
04-28 15:51:13.143: W/System.err(2915): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x870c918: Failure in SSL library, usually a protocol error
04-28 15:51:13.143: W/System.err(2915): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:658 0xb7c393a1:0x00000000)
04-28 15:51:13.143: W/System.err(2915): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:460)
04-28 15:51:13.143: W/System.err(2915): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257)
04-28 15:51:13.143: W/System.err(2915): at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210)
04-28 15:51:13.143: W/System.err(2915): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477)
04-28 15:51:13.153: W/System.err(2915): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:441)
04-28 15:51:13.153: W/System.err(2915): at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
04-28 15:51:13.153: W/System.err(2915): at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
04-28 15:51:13.153: W/System.err(2915): at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
04-28 15:51:13.153: W/System.err(2915): at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164)
04-28 15:51:13.153: W/System.err(2915): at com.ofss.fcdb.mobile.android.rms.helpers.NetworkConnector.getConnection(NetworkConnector.java:170)
04-28 15:51:13.153: W/System.err(2915): at com.ofss.fcdb.mobile.android.rms.util.InitiateRMS$2.run(InitiateRMS.java:221)
04-28 15:51:13.153: W/System.err(2915): at java.lang.Thread.run(Thread.java:856)
04-28 15:51:13.153: W/System.err(2915): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x870c918: Failure in SSL library, usually a protocol error
04-28 15:51:13.153: W/System.err(2915): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:658 0xb7c393a1:0x00000000)
04-28 15:51:13.153: W/System.err(2915): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
04-28 15:51:13.153: W/System.err(2915): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:410)
04-28 15:51:13.153: W/System.err(2915): ... 11 more
04-28 16:42:44.139: W/ResourceType(3140): No package identifier when getting value for resource number 0x00000000
android
ssl
sslhandshakeexception
android-4.0.3-ice-cream-sandwich
Bhavit S. Sengar
quelle
quelle
Antworten:
Ich fand die Lösung dafür, indem ich die Datenpakete mit Wireshark analysierte. Was ich fand, war, dass Android beim Herstellen einer sicheren Verbindung von TLSv1 auf SSLv3 zurückfiel . Es ist ein Fehler in Android-Versionen <4.4 und kann behoben werden, indem das SSLv3-Protokoll aus der Liste der aktivierten Protokolle entfernt wird. Ich habe eine benutzerdefinierte socketFactory-Klasse namens NoSSLv3SocketFactory.java erstellt. Verwenden Sie dies, um eine Socketfactory zu erstellen.
Verwenden Sie diese Klasse beim Verbinden wie folgt:
UPDATE:
Die richtige Lösung wäre nun die Installation eines neueren Sicherheitsanbieters mithilfe von Google Play Services :
Auf diese Weise erhält Ihre App effektiv Zugriff auf eine neuere Version von OpenSSL und Java Security Provider, die TLSv1.2 in SSLEngine unterstützt. Sobald der neue Anbieter installiert ist, können Sie eine SSLEngine erstellen, die SSLv3, TLSv1, TLSv1.1 und TLSv1.2 auf die übliche Weise unterstützt:
Oder Sie können die aktivierten Protokolle mit einschränken
engine.setEnabledProtocols
.Vergessen Sie nicht, die folgende Abhängigkeit hinzuzufügen ( überprüfen Sie die neueste Version hier ):
Weitere Informationen finden Sie unter diesem Link .
quelle
Szenario
Ich habe SSLHandshake-Ausnahmen auf Geräten erhalten, auf denen Versionen von Android vor Android 5.0 ausgeführt wurden. In meinem Anwendungsfall wollte ich auch einen TrustManager erstellen, um meinem Client-Zertifikat zu vertrauen.
Ich habe NoSSLv3SocketFactory und NoSSLv3Factory implementiert , um SSLv3 aus der Liste der unterstützten Protokolle meines Clients zu entfernen, aber ich konnte keine dieser Lösungen zum .
Einige Dinge, die ich gelernt habe:
Was hat bei mir funktioniert?
Lassen Sie die Sicherheit
Provider
von Android beim Starten Ihrer App aktualisieren.Der Standardanbieter vor 5.0+ deaktiviert SSLv3 nicht. Vorausgesetzt, Sie haben Zugriff auf Google Play-Dienste, ist es relativ einfach, den Sicherheitsanbieter von Android über Ihre App zu patchen.
Wenn Sie jetzt Ihren OkHttpClient oder HttpURLConnection erstellen, sollten TLSv1.1 und TLSv1.2 als Protokolle verfügbar sein und SSLv3 sollte entfernt werden. Wenn der Client / die Verbindung (oder genauer gesagt der SSLContext) vor dem Aufruf initialisiert wurde,
ProviderInstaller.installIfNeeded(...)
muss sie neu erstellt werden.Vergessen Sie nicht, die folgende Abhängigkeit hinzuzufügen ( neueste Version hier ):
Quellen:
Beiseite
Ich musste nicht explizit festlegen, welche Verschlüsselungsalgorithmen mein Client verwenden soll, aber ich fand einen SO-Beitrag, in dem diejenigen empfohlen wurden, die zum Zeitpunkt des Schreibens als am sichersten galten: Welche Cipher Suites sollten für SSL Socket aktiviert werden?
quelle
Außerdem sollten Sie wissen, dass Sie TLS v1.2 für Android 4.0-Geräte erzwingen können, für die es standardmäßig nicht aktiviert ist:
Fügen Sie diesen Code in onCreate () Ihrer Anwendungsdatei ein :
quelle
Früher habe ich dieses Problem auch mit einer benutzerdefinierten
SSLFactory
Implementierung gelöst , aber laut OkHttp-Dokumenten ist die Lösung viel einfacher.Meine endgültige Lösung mit den erforderlichen
TLS
Chiffren für Geräte ab 4.2 sieht folgendermaßen aus:Beachten Sie, dass der Satz unterstützter Protokolle von der Konfiguration auf Ihrem Server abhängt.
quelle
Ich habe die Lösung hier in diesem Link gefunden .
Sie müssen nur den folgenden Code in Ihre Android-Anwendungsklasse einfügen. Und das ist genug. Sie müssen keine Änderungen an Ihren Retrofit-Einstellungen vornehmen. Es hat meinen Tag gerettet.
Hoffe das wird hilfreich sein. Danke dir.
quelle
Das hat es für mich gelöst:
Android 4.1. Aktivieren Sie tls1.1 und tls 1.2
quelle
Ich habe auch dieses Problem mit der Fehlermeldung. Mein Code ist unten.
Ich habe meinen Springboot als Backend und verwende Android OKHttp, um Informationen zu erhalten. Der kritische Fehler, den ich gemacht habe, war, dass ich eine .url ( "https : //10.0.2.2: 8010 / getShopInfo / aaa") im Code von Android verwende. Aber die my backend ist keine https Anfrage erlaubt. Nachdem ich .url (" http : //10.0.2.2: 8010 / getShopInfo / aaa") verwendet habe , ist mein Code gut gelaufen . Ich möchte also sagen, dass mein Fehler nicht die Version des Emulators ist, sondern das Anforderungsprotokoll. Ich treffe ein anderes Problem, nachdem ich getan habe, was ich gesagt habe, aber es ist ein anderes Problem, und ich füge die Lösungsmethode des neuen Problems hinzu .
Viel Glück!
quelle
Es war nur reproduzierbar, wenn ich Proxy für Genymotion verwende (<4.4).
Überprüfen Sie Ihre Proxy-Einstellungen unter Einstellungen-> Drahtlos & Netzwerke-> WiFi -> (lange auf WiredSSID drücken) -> Netzwerk ändern
Wählen Sie Erweiterte Optionen anzeigen: Setzen Sie die Proxy-Einstellungen auf KEINE.
quelle
Als ich diesen Fehler bekam, lag es daran, dass die vom Server unterstützten Protokolle (TLS-Versionen) und / oder Cipher Suites auf dem Gerät nicht aktiviert waren (und möglicherweise nicht einmal vom Gerät unterstützt wurden). Für API 16-19 werden TLSv1.1 und TLSv1.2 unterstützt, aber standardmäßig nicht aktiviert. Nachdem ich sie für diese Versionen aktiviert habe, wurde immer noch der Fehler angezeigt, da diese Versionen keine der Chiffren in unserer Instanz von AWS CloudFront unterstützen.
Da es nicht möglich ist, Chiffren zu Android hinzuzufügen, mussten wir unsere CloudFront-Version von TLSv1.2_2018 auf TLSv1.1_2016 (das TLSv1.2 weiterhin unterstützt; es erfordert es nur nicht) umstellen, wobei vier der Chiffren von unterstützt werden die früheren Android-Versionen, von denen zwei immer noch als stark gelten.
Zu diesem Zeitpunkt verschwand der Fehler und die Anrufe wurden (mit TLSv1.2) weitergeleitet, da mindestens ein Protokoll und mindestens eine Verschlüsselung von Gerät und Server gemeinsam genutzt wurden.
Beachten Sie die Tabellen auf dieser Seite welche Protokolle und Chiffren von welchen Android-Versionen unterstützt und aktiviert werden.
Versuchte Android nun wirklich, SSLv3 zu verwenden, wie dies durch den Teil "sslv3-Alarm-Handshake-Fehler" in der Fehlermeldung impliziert wird? Ich bezweifle das; Ich vermute, dass dies ein altes Spinnennetz in der SSL-Bibliothek ist, das nicht bereinigt wurde, aber ich kann es nicht sicher sagen.
Um TLSv1.2 (und TLSv1.1) zu aktivieren, konnte ich eine viel einfachere
SSLSocketFactory
als die an anderer Stelle gezeigten verwenden (wieNoSSLv3SocketFactory
). Es wird lediglich sichergestellt, dass die aktivierten Protokolle alle unterstützten Protokolle enthalten und dass die aktivierten Chiffren alle unterstützten Chiffren enthalten (letzteres war für mich nicht erforderlich, könnte aber für andere sein) - sieheconfigure()
unten. Wenn Sie lieber nur die neuesten Protokolle aktivieren möchten, können Sie diese durchsocket.supportedProtocols
Folgendes ersetzenarrayOf("TLSv1.1", "TLSv1.2")
(ebenfalls für die Chiffren):quelle
Ich habe das Problem damit gelöst: NoSSLv3SocketFactory.java
Hauptklasse :
quelle
Meine Antwort entspricht in etwa den obigen Antworten, aber Sie müssen die Klasse genau schreiben, ohne etwas zu ändern.
}}
und um es mit HttpsURLConnection zu verwenden
quelle