Próbuję uruchomić następujący kod w systemie Android
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();
On l_connection.connect()
, podaje ten wyjątek SSLhandshakeException. Czasami to działa, ale w większości przypadków daje wyjątek. Dzieje się to tylko na emulatorze Androida 4.0. Przetestowałem to na Androidzie 4.4 i 5.0, działa dobrze. Co może być przyczyną tego ? Proszę pomóż
ŚLAD STOSU
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
źródło
źródło
Odpowiedzi:
Znalazłem rozwiązanie tego problemu, analizując pakiety danych za pomocą programu wireshark. Odkryłem, że podczas nawiązywania bezpiecznego połączenia Android wracał do SSLv3 z TLSv1 . Jest to błąd w Androidzie w wersji <4.4 i można go rozwiązać, usuwając protokół SSLv3 z listy włączonych protokołów. Zrobiłem niestandardową klasę socketFactory o nazwie NoSSLv3SocketFactory.java. Użyj tego do stworzenia fabryki gniazd.
Użyj tej klasy w ten sposób podczas łączenia:
AKTUALIZACJA :
Teraz poprawnym rozwiązaniem byłoby zainstalowanie nowszego dostawcy zabezpieczeń za pomocą usług Google Play :
To efektywnie daje Twojej aplikacji dostęp do nowszej wersji OpenSSL i Java Security Provider, która obejmuje obsługę TLSv1.2 w SSLEngine. Po zainstalowaniu nowego dostawcy możesz utworzyć SSLEngine, który obsługuje SSLv3, TLSv1, TLSv1.1 i TLSv1.2 w zwykły sposób:
Lub możesz ograniczyć włączone protokoły za pomocą
engine.setEnabledProtocols
.Nie zapomnij dodać następującej zależności ( sprawdź najnowszą wersję tutaj ):
Aby uzyskać więcej informacji, sprawdź ten link .
źródło
Scenariusz
Otrzymywałem wyjątki SSLHandshake na urządzeniach z wersjami Androida wcześniejszymi niż Android 5.0. W moim przypadku chciałem również utworzyć TrustManager, aby ufać certyfikatowi mojego klienta.
Zaimplementowałem NoSSLv3SocketFactory i NoSSLv3Factory, aby usunąć SSLv3 z listy obsługiwanych protokołów mojego klienta, ale żadne z tych rozwiązań nie działało.
Kilka rzeczy, których się nauczyłem:
Co mi pomogło
Zezwól zabezpieczeniom Androida na
Provider
aktualizację podczas uruchamiania aplikacji.Domyślny dostawca przed wersją 5.0+ nie wyłącza SSLv3. Pod warunkiem, że masz dostęp do usług Google Play, stosunkowo łatwo jest załatać dostawcę zabezpieczeń Androida z poziomu swojej aplikacji.
Jeśli teraz utworzysz OkHttpClient lub HttpURLConnection, TLSv1.1 i TLSv1.2 powinny być dostępne jako protokoły, a SSLv3 powinien zostać usunięty. Jeśli klient / połączenie (a dokładniej jest to SSLContext) zostało zainicjowane przed wywołaniem
ProviderInstaller.installIfNeeded(...)
, należy je odtworzyć.Nie zapomnij dodać następującej zależności ( najnowszą wersję można znaleźć tutaj ):
Źródła:
Na bok
Nie musiałem jawnie określać algorytmów szyfrowania, których powinien używać mój klient, ale znalazłem post SO zalecający te uważane za najbezpieczniejsze w momencie pisania: Które zestawy szyfrów włączyć dla gniazda SSL?
źródło
Powinieneś także wiedzieć, że możesz wymusić TLS v1.2 na urządzeniach z Androidem 4.0, które nie mają go domyślnie włączonego:
Umieść ten kod w onCreate () pliku aplikacji :
źródło
Wcześniej rozwiązałem również ten problem za pomocą niestandardowej
SSLFactory
implementacji, ale zgodnie z dokumentacją OkHttp rozwiązanie jest znacznie łatwiejsze.Moje ostateczne rozwiązanie z potrzebnymi
TLS
szyframi dla urządzeń 4.2+ wygląda następująco:Należy pamiętać, że zestaw obsługiwanych protokołów zależy od konfiguracji na serwerze.
źródło
Znalazłem rozwiązanie tutaj w tym linku .
Musisz tylko umieścić poniższy kod w swojej klasie aplikacji na Androida. I to wystarczy. Nie musisz wprowadzać żadnych zmian w ustawieniach modernizacji. To uratowało mi dzień.
Mam nadzieję, że to pomoże. Dziękuję Ci.
źródło
To rozwiązało to dla mnie:
android 4.1. włącz tls1.1 i tls 1.2
źródło
Mam też ten problem z raportem błędów. Mój kod jest poniżej.
Mam swojego Springboota jako moje zaplecze i używam Androida OKHttp, aby uzyskać informacje. Krytyczny błąd, jaki popełniłem, polegał na tym, że używam .url ( „https : //10.0.2.2: 8010 / getShopInfo / aaa”) w kodzie Androida. Ale mój backend nie jest dozwolony dla żądania https. Po użyciu .url („ http : //10.0.2.2: 8010 / getShopInfo / aaa”) kod poszedł dobrze. Więc chcę powiedzieć, że moim błędem nie jest wersja emulatora, a protokół żądania. Po wykonaniu tego, co powiedziałem, napotykam inny problem, ale jest to inny problem i dołączam metodę rozwiązania nowego problemu .
Powodzenia!
źródło
Było odtwarzalne tylko wtedy, gdy używam proxy na genymotion (<4.4).
Sprawdź ustawienia proxy w Ustawienia-> Sieci zwykłe i bezprzewodowe-> Wi-Fi -> (Długie naciśnięcie WiredSSID) -> Modyfikuj sieć
Wybierz pokaż opcje zaawansowane: ustaw Ustawienia proxy na BRAK.
źródło
Kiedy otrzymałem ten błąd, było to spowodowane tym, że protokoły (wersje TLS) i / lub mechanizmy szyfrowania obsługiwane przez serwer nie były włączone (i prawdopodobnie nawet nie były obsługiwane) na urządzeniu. W przypadku interfejsu API 16-19 protokoły TLSv1.1 i TLSv1.2 są obsługiwane, ale nie są domyślnie włączone. Po włączeniu ich dla tych wersji nadal otrzymuję błąd, ponieważ te wersje nie obsługują żadnego z szyfrów w naszej instancji AWS CloudFront.
Ponieważ nie jest możliwe dodanie szyfrów do Androida, musieliśmy zmienić naszą wersję CloudFront z TLSv1.2_2018 na TLSv1.1_2016 (który nadal obsługuje TLSv1.2; po prostu go nie wymaga), która ma cztery z nich obsługiwane przez wcześniejsze wersje Androida, z których dwie są nadal uważane za mocne.
W tym momencie błąd zniknął i połączenia były realizowane (z TLSv1.2), ponieważ istniał co najmniej jeden protokół i co najmniej jeden szyfr, który współużytkował urządzenie i serwer.
Zapoznaj się z tabelami na tej stronie, aby zobaczyć, które protokoły i szyfry są obsługiwane i włączone w poszczególnych wersjach Androida.
Czy system Android naprawdę próbował używać protokołu SSLv3, jak sugeruje to część komunikatu o błędzie „błąd uzgadniania alertu sslv3”? Wątpię; Podejrzewam, że to stara pajęczyna w bibliotece SSL, która nie została wyczyszczona, ale nie mogę powiedzieć na pewno.
Aby włączyć TLSv1.2 (i TLSv1.1), mogłem użyć znacznie prostszego
SSLSocketFactory
niż te widziane gdzie indziej (jakNoSSLv3SocketFactory
). Po prostu upewnia się, że włączone protokoły obejmują wszystkie obsługiwane protokoły, a włączone szyfry obejmują wszystkie obsługiwane szyfry (te ostatnie nie były dla mnie konieczne, ale mogą być dla innych) - patrzconfigure()
na dole. Jeśli wolisz włączyć tylko najnowsze protokoły, możesz zastąpićsocket.supportedProtocols
czymś takimarrayOf("TLSv1.1", "TLSv1.2")
(podobnie jak szyfry):źródło
Rozwiązałem problem w ten sposób: NoSSLv3SocketFactory.java
Klasa główna:
źródło
Moja odpowiedź jest zbliżona do powyższych odpowiedzi, ale musisz dokładnie napisać zajęcia, nie zmieniając niczego.
}
i używać go z HttpsURLConnection
źródło