Entgegen der akzeptierten Antwort Sie nicht Wenn Sie einen benutzerdefinierten Trust-Manager benötigen, müssen Sie Ihre Serverkonfiguration korrigieren!
Ich habe das gleiche Problem beim Herstellen einer Verbindung zu einem Apache-Server mit einem falsch installierten Dynadot/Alphassl-Zertifikat. Ich verbinde mich mit HttpsUrlConnection (Java/Android), was geworfen hat –
javax.net.ssl.SSLHandshakeException:
java.security.cert.CertPathValidatorException:
Trust anchor for certification path not found.
Das eigentliche Problem ist eine Server-Fehlkonfiguration – testen Sie es mit http://www.digicert.com/help/ oder ähnliches, und es wird Ihnen sogar die Lösung sagen:
“Das Zertifikat wurde nicht von einer vertrauenswürdigen Stelle signiert (Prüfung anhand des Stammspeichers von Mozilla). Wenn Sie das Zertifikat von einer vertrauenswürdigen Stelle gekauft haben, Sie müssen wahrscheinlich nur ein oder mehrere Zwischenzertifikate installieren. Wenden Sie sich an Ihren Zertifikatsanbieter, um Unterstützung dabei für Ihre Serverplattform zu erhalten.”
Sie können das Zertifikat auch mit openssl überprüfen:
Verify return code: 21 (unable to verify the first certificate)
und früher in der Ausgabe:
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=21:unable to verify the first certificate`
Die Zertifikatskette enthält nur 1 Element (Ihr Zertifikat):
Certificate chain
0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
i:/O=AlphaSSL/CN=AlphaSSL CA - G2
… sollte aber die Signaturautoritäten in einer Kette auf eine zurückverweisen, der Android vertraut (Verisign, GlobalSign usw.):
Certificate chain
0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
i:/O=AlphaSSL/CN=AlphaSSL CA - G2
1 s:/O=AlphaSSL/CN=AlphaSSL CA - G2
i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
2 s:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
Nach der Installation der von meinem Zertifikatsaussteller bereitgestellten Zwischenzertifikate habe ich jetzt keine Fehler mehr, wenn ich eine Verbindung über HttpsUrlConnection herstelle.
Falls das OP Zugriff auf die SSL-Konfiguration des Servers hat, mit dem es sich verbindet, könnte dies eine Lösung sein. Aber wenn er nicht derjenige ist, der den Dienst hostet, mit dem er sich verbindet, muss er das Problem auf seiner Seite beheben, was bedeutet, dass er einen benutzerdefinierten Trust-Manager implementiert.
– Mathias B
30. April 2013 um 15:24 Uhr
Ihre Lösung funktioniert, keine Frage, aber stimmen Sie nicht zu, dass es sich eher um eine Problemumgehung als um eine Behebung der Grundursache handelt? Wenn ich von 3 Clients (Android, iOS, Windows Mobile) eine Verbindung zu einem Server herstellen muss, muss ich die Problemumgehung auf alle 3 anwenden, während ich den Server einmal reparieren kann und alle “einfach funktionieren”.
– Stevie
30. April 2013 um 16:18 Uhr
Danke Stevie, ich hatte meinen Server 3 Monate lang falsch konfiguriert und erst jetzt habe ich das entdeckt! Jetzt funktioniert meine Android-App zu 100 %
– jpros
5. September 2013 um 20:01 Uhr
@Stevie Ich mache viele Aufrufe an verschiedene APIs, die dieselbe Domäne teilen, aber nur einer von ihnen schlägt mit (javax.net.ssl.SSLHandshakeException) fehl … irgendeine Idee, warum so etwas passieren würde? Übrigens ist das SSL-Zertifikat nicht vertrauenswürdig. Also dachte ich, dass alle Aufrufe mit derselben Ausnahme fehlschlagen sollten.
– ein fairer Spieler
3. März 2014 um 6:39 Uhr
@dvaey nimm Kontakt mit dem Besitzer des Servers auf und sage ihm, dass seine Konfiguration kaputt ist und sein https nicht richtig funktioniert – gib ihm diesen Link, um es zu beweisen digicert.com/help … Ich stelle mir vor, sie wären dankbar und würden schnell eine Lösung finden. Andernfalls müssen Sie einen der Workaround-Schritte in den anderen Antworten ausführen, aber dann müssen Sie entweder keine Sicherheit akzeptieren (Zertifikate ignorieren) oder Ihre Apps erneut bereitstellen, wenn das Zertifikat abläuft und Ihr benutzerdefinierter Trust Store nicht mehr mit dem neuen übereinstimmt zert.
– Stevie
20. November 2015 um 10:00 Uhr
Mathias B
Die Lösung von @Chrispix ist gefährlich! Wenn man allen Zertifikaten vertraut, kann jeder einen Man-in-the-Middle-Angriff durchführen! Senden Sie einfach ein beliebiges Zertifikat an den Client und er wird es akzeptieren!
Fügen Sie Ihre Zertifikate zu einem benutzerdefinierten Trust-Manager hinzu, wie in diesem Beitrag beschrieben: Allen Zertifikaten mit HttpClient über HTTPS vertrauen
Obwohl es etwas komplexer ist, eine sichere Verbindung mit einem benutzerdefinierten Zertifikat herzustellen, bringt es Ihnen die gewünschte SSL-Verschlüsselungssicherheit ohne die Gefahr eines Man-in-the-Middle-Angriffs!
Dies ist in Ordnung, um mit einem selbst generierten Zertifikat zu arbeiten, aber für eines (wie das OP), das eine gültige Kette zurück zu den Stammzertifizierungsstellen hat, ist es nur eine Problemumgehung für einen schlecht konfigurierten Server – siehe meine Antwort.
– Stevie
30. April 2013 um 14:43 Uhr
@Stevie Das Akzeptieren JEDES Zertifikats ist nur eine Option für einen Proof-of-Concept-Test, bei dem die SSL-Verbindung nicht der Teil ist, den Sie testen möchten. Andernfalls müssen Sie SSL nicht verwenden, wenn Sie jedes Zertifikat akzeptieren, da die Verbindung nicht sicher ist!
– Mathias B
30. April 2013 um 15:26 Uhr
Ah, tut mir leid, ich glaube, da liegt ein Missverständnis vor – ich stimme vollkommen zu, dass niemand jemals jedes Zertifikat akzeptieren sollte! 🙂 Mein Kommentar bezog sich auf Ihren zweiten Absatz – den Vorschlag, einen benutzerdefinierten Trust-Manager zu verwenden -, der meiner Meinung nach eher ein letzter Ausweg als eine empfohlene Lösung sein sollte.
– Stevie
30. April 2013 um 16:25 Uhr
Kopf hoch.. Ich habe die ‘Lösung’ entfernt, die ich als Problemumgehung eingefügt hatte, um keine weiteren Probleme zu verursachen, da die Leute es nicht als ‘vorübergehende Problemumgehung’ betrachteten.
– Chrispix
28. Januar 2016 um 20:41 Uhr
@Chrispix, du hättest die Teilkorrektur nicht entfernen sollen, sie ist nur für Testzwecke gut
– Hugo Allexis Cardona
19. September 2017 um 3:27 Uhr
Sie können bestimmten Zertifikaten zur Laufzeit vertrauen.
Laden Sie es einfach vom Server herunter, legen Sie Assets ein und laden Sie es so mit ssl-utils-android:
Im obigen Beispiel habe ich verwendet OkHttpClient aber SSLContext kann mit jedem Client in Java verwendet werden.
Wenn Sie Fragen haben, können Sie diese gerne stellen. Ich bin der Autor dieser kleinen Bibliothek.
Was ist mit .pfx?
– Choletski
27. Oktober 2018 um 21:02 Uhr
Ist das nicht unsicher, da jeder Benutzer auf den Assets-Ordner für eine App zugreifen kann, sobald er die APK hat?
– Patrice Andala
4. Oktober 2019 um 13:57 Uhr
@PatriceAndala, Root-CAs sind öffentlich verfügbar, also ist es in Ordnung
– BekaBot
15. Juni 2020 um 7:07 Uhr
Danke, wenn SSL alle 2 Monate erneuert wird, müssen wir dann alle 2 Monate eine neue CER-Datei in der App ersetzen?
– Resa
14. Oktober 2021 um 16:56 Uhr
Benutzer1506104
Update basierend auf der neuesten Android-Dokumentation (März 2017):
Wenn Sie diese Art von Fehler erhalten:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:374)
at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)
at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)
at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)
Das Problem könnte eines der folgenden sein:
Die Zertifizierungsstelle, die das Serverzertifikat ausgestellt hat, war unbekannt
Das Serverzertifikat wurde nicht von einer Zertifizierungsstelle signiert, sondern war selbstsigniert
Der Serverkonfiguration fehlt eine Zwischenzertifizierungsstelle
Andere, die verwenden AsyncHTTPClient von com.loopj.android:android-async-http Bibliothek, überprüfen Sie bitte Setup AsyncHttpClient, um HTTPS zu verwenden.
Schihab Uddin
Wenn Sie Nachrüstung verwenden, müssen Sie Ihre anpassen OkHttpClient.
retrofit = new Retrofit.Builder()
.baseUrl(ApplicationData.FINAL_URL)
.client(getUnsafeOkHttpClient().build())
.addConverterFactory(GsonConverterFactory.create())
.build();
Der vollständige Code ist wie folgt.
public class RestAdapter {
private static Retrofit retrofit = null;
private static ApiInterface apiInterface;
public static OkHttpClient.Builder getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
return builder;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static ApiInterface getApiClient() {
if (apiInterface == null) {
try {
retrofit = new Retrofit.Builder()
.baseUrl(ApplicationData.FINAL_URL)
.client(getUnsafeOkHttpClient().build())
.addConverterFactory(GsonConverterFactory.create())
.build();
} catch (Exception e) {
e.printStackTrace();
}
apiInterface = retrofit.create(ApiInterface.class);
}
return apiInterface;
}
}
Ich versuche, Code zu verwenden, aber ich erhalte erneut den folgenden Fehler. kannst du dabei helfen
– Vishwa Pratap
28. Februar 2019 um 17:39 Uhr
Das ist radikal unsicher. Verwende nicht.
– Benutzer207421
7. November 2019 um 1:24 Uhr
Danke! Methode umgeschrieben getUnsafeOkHttpClient() in Kotlin: stackoverflow.com/a/60507560/2914140.
– CoolMind
3. März 2020 um 12:46 Uhr
user28434’mschritt
Antwort auf sehr alten Beitrag. Aber vielleicht hilft es einigen Neulingen und wenn nichts davon funktioniert.
Erläuterung: Ich weiß, niemand will Erklärungsmist; eher die Lösung. Aber in einem Liner versuchen Sie, auf einen Dienst von Ihrem lokalen Computer auf einen Remote-Computer zuzugreifen, der Ihrem Computer nicht vertraut. Sie müssen das Vertrauen vom Remote-Server anfordern.
Lösung: Die folgende Lösung geht davon aus, dass Sie die folgenden Bedingungen erfüllt haben
Es wird versucht, von Ihrem lokalen Computer aus auf eine Remote-API zuzugreifen.
Sie bauen für Android-Apps
Ihr Remote-Server befindet sich unter Proxy-Filterung (Sie verwenden Proxy in Ihren Browsereinstellungen, um auf den Remote-API-Dienst zuzugreifen, normalerweise ein Staging- oder Entwicklungsserver)
Sie testen auf einem echten Gerät
Schritte:
Sie benötigen eine .keystore-Erweiterungsdatei, um Ihre App zu registrieren. Wenn Sie nicht wissen, wie man eine .keystore-Datei erstellt; dann folgen Sie dem Folgenden Abschnitt .keystore-Datei erstellen oder springen Sie andernfalls zum nächsten Abschnitt Apk-Datei signieren
Erstellen Sie eine .keystore-Datei
Öffnen Sie Android Studio. Klicken Sie auf das obere Menü Build > Generate Signed APK. Klicken Sie im nächsten Fenster auf die Erstelle neu… Taste. Geben Sie im neuen Fenster bitte Daten in alle Felder ein. Denken Sie daran, dass die beiden von mir empfohlenen Passwortfelder dasselbe Passwort haben sollten. kein anderes Passwort verwenden; und merken Sie sich auch den Speicherpfad im obersten Feld Schlüsselspeicherpfad:. Nachdem Sie alle Felder ausgefüllt haben, klicken Sie auf die Schaltfläche OK.
Apk-Datei signieren
Jetzt müssen Sie eine signierte App mit der gerade erstellten .keystore-Datei erstellen. Folge diesen Schritten
Erstellen > Projekt bereinigen, warten Sie, bis die Reinigung abgeschlossen ist
Erstellen > Signiertes APK generieren
Klicken Choose existing... Taste
Wählen Sie die .keystore-Datei aus, die wir gerade in der erstellt haben Erstellen Sie eine .keystore-Datei Sektion
Geben Sie das gleiche Passwort ein, das Sie beim Erstellen erstellt haben Erstellen Sie eine .keystore-Datei Sektion. Verwenden Sie das gleiche Passwort für Key store password und Key password Felder. Geben Sie auch den Alias ein
Klicken Sie auf die Schaltfläche Weiter
Im nächsten Bildschirm; Dies kann je nach Ihren Einstellungen in unterschiedlich sein build.gradle Dateien, müssen Sie auswählen Build Types und Flavors.
Für die Build Types wählen release aus der Dropdown-Liste
Zum Flavors Dies hängt jedoch von Ihren Einstellungen ab build.gradle Datei. Wählen staging aus diesem Bereich. Ich habe die folgenden Einstellungen in der build.gradleSie können dasselbe wie meins verwenden, aber stellen Sie sicher, dass Sie das ändern applicationId zu Ihrem Paketnamen
Klicken Sie auf die unteren beiden Signature Versions Kontrollkästchen und klicken Sie darauf Finish Taste.
Fast dort:
All die harte Arbeit ist getan, jetzt die Bewegung der Wahrheit. Um auf den per Proxy gesicherten Staging-Server zugreifen zu können, müssen Sie einige Einstellungen in Ihren echten Test-Android-Geräten vornehmen.
Proxy-Einstellung im Android-Gerät:
Klicken Sie im Android-Telefon auf die Einstellung und dann auf Wi-Fi
Drücken Sie lange auf das verbundene WLAN und wählen Sie es aus Modify network
Drücke den Advanced options wenn du das nicht sehen kannst Proxy Hostname Bereich
In dem Proxy Hostname Geben Sie die Host-IP oder den Namen ein, mit dem Sie sich verbinden möchten. Ein typischer Staging-Server wird als benannt stg.api.mygoodcompany.com
Geben Sie für den Port beispielsweise die vierstellige Portnummer ein 9502
Schlagen Sie die Save Taste
Ein letzter Stopp:
Denken Sie daran, dass wir die signierte APK-Datei in generiert haben APK-Datei signieren Sektion. Jetzt ist es an der Zeit, diese APK-Datei zu installieren.
Öffnen Sie ein Terminal und wechseln Sie in den Ordner mit den signierten APK-Dateien
Verbinden Sie Ihr Android-Gerät mit Ihrem Gerät
Entfernen Sie alle zuvor installierten APK-Dateien vom Android-Gerät
Laufen adb installname of the apk file
Wenn aus irgendeinem Grund der obige Befehl mit zurückkehrt adb command not found. Geben Sie den vollständigen Pfad als ein C:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exeinstallname of the apk file
Ich hoffe das Problem lässt sich lösen. Wenn nicht, hinterlassen Sie mir bitte einen Kommentar.
Salam!
Ich versuche, Code zu verwenden, aber ich erhalte erneut den folgenden Fehler. kannst du dabei helfen
– Vishwa Pratap
28. Februar 2019 um 17:39 Uhr
Das ist radikal unsicher. Verwende nicht.
– Benutzer207421
7. November 2019 um 1:24 Uhr
Danke! Methode umgeschrieben getUnsafeOkHttpClient() in Kotlin: stackoverflow.com/a/60507560/2914140.
import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.*
import javax.security.cert.CertificateException
object {
val okHttpClient: OkHttpClient
val gson: Gson
val retrofit: Retrofit
init {
okHttpClient = getOkHttpBuilder()
// Other parameters like connectTimeout(15, TimeUnit.SECONDS)
.build()
gson = GsonBuilder().setLenient().create()
retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
}
fun getOkHttpBuilder(): OkHttpClient.Builder =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
OkHttpClient().newBuilder()
} else {
// Workaround for the error "Caused by: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate: Certificate expired at".
getUnsafeOkHttpClient()
}
private fun getUnsafeOkHttpClient(): OkHttpClient.Builder =
try {
// Create a trust manager that does not validate certificate chains
val trustAllCerts: Array<TrustManager> = arrayOf(
object : X509TrustManager {
@Throws(CertificateException::class)
override fun checkClientTrusted(chain: Array<X509Certificate?>?,
authType: String?) = Unit
@Throws(CertificateException::class)
override fun checkServerTrusted(chain: Array<X509Certificate?>?,
authType: String?) = Unit
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
}
)
// Install the all-trusting trust manager
val sslContext: SSLContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, SecureRandom())
// Create an ssl socket factory with our all-trusting manager
val sslSocketFactory: SSLSocketFactory = sslContext.socketFactory
val builder = OkHttpClient.Builder()
builder.sslSocketFactory(sslSocketFactory,
trustAllCerts[0] as X509TrustManager)
builder.hostnameVerifier { _, _ -> true }
builder
} catch (e: Exception) {
throw RuntimeException(e)
}
}
Derselbe Fehler wird auch angezeigt, wenn Sie verwenden Glide, Bilder werden nicht angezeigt. Um dies zu umgehen, siehe Glide – javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Vertrauensanker für Zertifizierungspfad nicht gefunden und How to set OkHttpClient for glide.
@GlideModule
class MyAppGlideModule : AppGlideModule() {
val okHttpClient = Api.getOkHttpBuilder().build() // Api is the class written above.
// It is better to create okHttpClient here and not use Api.okHttpClient,
// because their settings may differ. For instance, it can use its own
// `addInterceptor` and `addNetworkInterceptor` that can affect on a read JSON.
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
registry.replace(GlideUrl::class.java, InputStream::class.java,
OkHttpUrlLoader.Factory(okHttpClient))
}
}