Ich habe ein Problem mit der autorisierten SSL-Verbindung. Ich habe eine Struts-Aktion erstellt, die mit einem vom Client autorisierten SSL-Zertifikat eine Verbindung zu einem externen Server herstellt. In meiner Aktion versuche ich, einige Daten an den Bankserver zu senden, aber ohne Glück, da ich vom Server den folgenden Fehler habe:
error: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
Meine Methode aus meiner Aktionsklasse, die Daten an den Server sendet
//Getting external IP from host
URL whatismyip = new URL("http://automation.whatismyip.com/n09230945.asp");
BufferedReader inIP = new BufferedReader(new InputStreamReader(whatismyip.openStream()));
String IPStr = inIP.readLine(); //IP as a String
Merchant merchant;
System.out.println("amount: " + amount + ", currency: " + currency + ", clientIp: " + IPStr + ", description: " + description);
try {
merchant = new Merchant(context.getRealPath("/") + "merchant.properties");
} catch (ConfigurationException e) {
Logger.getLogger(HomeAction.class.getName()).log(Level.INFO, "message", e);
System.err.println("error: " + e.getMessage());
return ERROR;
}
String result = merchant.sendTransData(amount, currency, IPStr, description);
System.out.println("result: " + result);
return SUCCESS;
Meine Merchant.properties-Datei:
bank.server.url=https://-servernameandport-/
https.cipher=-cipher-
keystore.file=-key-.jks
keystore.type=JKS
keystore.password=-password-
ecomm.server.version=2.0
encoding.source=UTF-8
encoding.native=UTF-8
Zum ersten Mal dachte ich, dass dies ein Zertifikatsproblem ist. Ich habe es von .pfx in .jks konvertiert, aber ich habe den gleichen Fehler ohne Änderungen.
Antworten:
Der Handshake-Fehler kann verschiedene Ursachen haben:
Da der zugrunde liegende Fehler nicht lokalisiert werden kann, ist es besser, das
-Djavax.net.debug=all
Flag einzuschalten, um das Debuggen der hergestellten SSL-Verbindung zu ermöglichen. Bei eingeschaltetem Debug können Sie feststellen, welche Aktivität im Handshake fehlgeschlagen ist.Aktualisieren
Basierend auf den jetzt verfügbaren Details scheint das Problem auf einen unvollständigen Zertifikatvertrauenspfad zwischen dem an den Server ausgestellten Zertifikat und einer Stammzertifizierungsstelle zurückzuführen zu sein. In den meisten Fällen liegt dies daran, dass das Zertifikat der Stammzertifizierungsstelle im Vertrauensspeicher nicht vorhanden ist, was dazu führt, dass kein Zertifikatvertrauenspfad vorhanden sein kann. Das Zertifikat ist vom Kunden im Wesentlichen nicht vertrauenswürdig. Browser können eine Warnung anzeigen , damit Benutzer dies ignorieren können. Dies gilt jedoch nicht für SSL-Clients (wie die HttpsURLConnection- Klasse oder eine HTTP-Client-Bibliothek wie Apache HttpComponents Client ).
Die meisten dieser Clientklassen / -bibliotheken würden sich auf den Vertrauensspeicher stützen, der von der JVM für die Zertifikatvalidierung verwendet wird. In den meisten Fällen ist dies die
cacerts
Datei im Verzeichnis JRE_HOME / lib / security. Wenn der Speicherort des Vertrauensspeichers mithilfe der JVM-Systemeigenschaft angegeben wurdejavax.net.ssl.trustStore
, wird der Speicher in diesem Pfad normalerweise von der Clientbibliothek verwendet. Wenn Sie Zweifel haben, schauen Sie sich IhreMerchant
Klasse an und finden Sie heraus, mit welcher Klasse / Bibliothek die Verbindung hergestellt wird.Durch Hinzufügen der Zertifikatzertifizierungsstelle des Servers zu diesem Vertrauensspeicher sollte das Problem behoben werden. Sie können sich auf meine Antwort zu einer verwandten Frage zum Abrufen von Tools für diesen Zweck beziehen , aber das Java-Dienstprogramm keytool ist für diesen Zweck ausreichend.
Warnung : Der Trust Store ist im Wesentlichen die Liste aller CAs, denen Sie vertrauen. Wenn Sie ein Zertifikat eingeben, das nicht zu einer Zertifizierungsstelle gehört, der Sie nicht vertrauen, können SSL / TLS-Verbindungen zu Sites mit von dieser Entität ausgestellten Zertifikaten entschlüsselt werden, wenn der private Schlüssel verfügbar ist.
Update Nr. 2: Grundlegendes zur Ausgabe des JSSE-Trace
Der Keystore und die von der JVM verwendeten Truststores werden normalerweise ganz am Anfang aufgelistet, ähnlich wie folgt:
Wenn der falsche Truststore verwendet wird, müssen Sie das Serverzertifikat erneut in das richtige Zertifikat importieren oder den Server für die Verwendung des aufgelisteten Zertifikats neu konfigurieren (nicht empfohlen, wenn Sie mehrere JVMs haben und alle für unterschiedliche verwendet werden Bedürfnisse).
Wenn Sie überprüfen möchten, ob die Liste der Vertrauenszertifikate die erforderlichen Zertifikate enthält, gibt es einen Abschnitt dafür, der wie folgt beginnt:
Sie müssen suchen, ob die Zertifizierungsstelle des Servers ein Thema ist.
Der Handshake-Prozess enthält einige wichtige Einträge (Sie müssen SSL kennen, um sie im Detail zu verstehen. Zum Debuggen des aktuellen Problems reicht es jedoch aus zu wissen, dass ein handshake_failure normalerweise im ServerHello gemeldet wird.
1. ClientHallo
Eine Reihe von Einträgen wird gemeldet, wenn die Verbindung initialisiert wird. Die erste vom Client in einem SSL / TLS-Verbindungsaufbau gesendete Nachricht ist die ClientHello-Nachricht, die normalerweise in den Protokollen wie folgt gemeldet wird:
Beachten Sie die verwendeten Cipher Suites. Dies muss möglicherweise mit dem Eintrag in Ihrer Merchant.properties-Datei übereinstimmen , da dieselbe Konvention möglicherweise von der Bibliothek der Bank verwendet wird. Wenn die verwendete Konvention anders ist, besteht kein Grund zur Sorge, da ServerHello dies angibt, wenn die Verschlüsselungssuite nicht kompatibel ist.
2. ServerHallo
Der Server antwortet mit einem ServerHello, das angibt, ob der Verbindungsaufbau fortgesetzt werden kann. Einträge in den Protokollen sind normalerweise vom folgenden Typ:
Beachten Sie die ausgewählte Chiffresuite. Dies ist die beste Suite, die sowohl dem Server als auch dem Client zur Verfügung steht. Normalerweise wird die Verschlüsselungssuite nicht angegeben, wenn ein Fehler auftritt. Das Zertifikat des Servers (und optional der gesamten Kette) wird vom Server gesendet und befindet sich in den Einträgen wie folgt:
Wenn die Überprüfung des Zertifikats erfolgreich war, finden Sie einen Eintrag ähnlich dem folgenden:
Einer der oben genannten Schritte wäre nicht erfolgreich gewesen, was zu einem Handshake-Fehler geführt hätte, da der Handshake in dieser Phase normalerweise abgeschlossen ist (nicht wirklich, aber die nachfolgenden Phasen des Handshakes verursachen normalerweise keinen Handshake-Fehler). Sie müssen herausfinden, welcher Schritt fehlgeschlagen ist, und die entsprechende Nachricht als Aktualisierung der Frage veröffentlichen (es sei denn, Sie haben die Nachricht bereits verstanden und wissen, wie Sie sie beheben können).
quelle
keytool -list -v -keystore $JAVA_HOME/jre/lib/security/cacerts
Befehl verwenden, um den Inhalt auszudrucken. Überprüfen Sie anschließend, ob die Zertifikate in den Zertifikaten mit der Zertifizierungsstelle des Bankzertifikats übereinstimmen.changeit
. Es sei denn, es wurde geändert.Durch die Installation der unbegrenzten Stärke der Java Cryptography Extension (JCE) ( für JDK7 | für JDK8 ) kann dieser Fehler möglicherweise behoben werden . Entpacken Sie die Datei und folgen Sie der Readme-Datei, um sie zu installieren.
quelle
Der Handshake-Fehler kann eine fehlerhafte Implementierung des TLSv1-Protokolls sein.
In unserem Fall hat dies bei Java 7 geholfen:
Das JVM wird in dieser Reihenfolge verhandeln. Die Server mit dem neuesten Update werden 1.2 ausführen, die fehlerhaften Server werden auf Version 1 heruntergefahren und das funktioniert mit der ähnlichen Version 1 in Java 7.
quelle
Dies kann auch passieren, wenn der Client ein Zertifikat vorlegen muss. Nachdem der Server die Zertifikatkette aufgelistet hat, kann Folgendes passieren:
3. Zertifikatanforderung Der Server gibt eine Zertifikatanforderung vom Client aus. Die Anforderung listet alle Zertifikate auf, die der Server akzeptiert.
4. Client-Zertifikatkette Dies ist das Zertifikat, das der Client an den Server sendet.
Wenn die Kette kein Zertifikat enthält und der Server eines benötigt, wird hier der Handshake-Fehler angezeigt. Eine wahrscheinliche Ursache ist, dass der Pfad zu Ihrem Zertifikat nicht gefunden wurde.
5. Zertifikatüberprüfung Der Client fordert den Server auf, das Zertifikat zu überprüfen
Dieser Schritt wird nur ausgeführt, wenn Sie ein Zertifikat senden.
6. Fertig Der Server antwortet mit einer Bestätigungsantwort
quelle
Ich denke nicht, dass dies das Problem für den ersten Fragesteller löst, sondern für Googler, die hierher kommen, um Antworten zu erhalten:
Bei Update 51 verbot Java 1.8 standardmäßig [1] RC4-Chiffren, wie auf der Seite mit den Versionshinweisen zu sehen ist:
Wenn Ihr Server diese Verschlüsselung stark bevorzugt (oder nur diese Verschlüsselung verwendet), kann dies ein
handshake_failure
On-Java auslösen .Sie können die Verbindung zum Server testen, um RC4-Chiffren zu aktivieren (versuchen Sie zunächst ohne
enabled
Argument, festzustellen, ob a ausgelöst wirdhandshake_failure
, und setzen Sie dannenabled
:1 - https://www.java.com/de/download/faq/release_changes.xml
quelle
Ich habe diesen Fehler, als ich versucht habe, JDK 1.7 zu verwenden. Als ich mein JDK auf jdk1.8.0_66 aktualisierte, funktionierte alles einwandfrei.
Die einfachste Lösung für dieses Problem könnte also sein: Aktualisieren Sie Ihr JDK und es könnte gut funktionieren.
quelle
In meinem Fall wird cert importiert, der Fehler bleibt bestehen und wird durch Hinzufügen
System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
vor dem Verbinden behobenquelle
Angenommen, Sie verwenden die richtigen SSL / TLS-Protokolle, haben Ihr
keyStore
und ordnungsgemäß konfigurierttrustStore
und bestätigt, dass keine Probleme mit den Zertifikaten selbst vorliegen, müssen Sie möglicherweise Ihre Sicherheitsalgorithmen stärken .Wie in der Antwort von Vineet erwähnt , ist ein möglicher Grund, warum Sie diesen Fehler erhalten, die Verwendung inkompatibler Chiffresuiten. Durch Aktualisieren von my
local_policy
undUS_export_policy
jars imsecurity
Ordner meines JDK mit denen in der Java Cryptography Extension (JCE) konnte ich den Handshake erfolgreich abschließen.quelle
Ich habe heute das gleiche Problem mit dem OkHttp-Client, um eine https-basierte URL zu erhalten. Dies wurde durch die Nichtübereinstimmung der HTTP-Protokollversion und der Cipher-Methode zwischen Server- und Client-Seite verursacht .
1) Überprüfen Sie die https-Protokollversion und die Verschlüsselungsmethode Ihrer Website.openssl>s_client -connect your_website.com:443 -showcerts
Sie erhalten viele Detailinformationen, die wichtigsten Informationen sind wie folgt aufgeführt:
2) Konfigurieren Sie Ihren http-Client beispielsweise im Fall eines OkHttp-Clients :Dies wird bekommen, was wir wollen.
quelle
Ich habe einen HTTPS-Server gefunden, der auf diese Weise fehlgeschlagen ist, wenn mein Java-Client-Prozess mit konfiguriert wurde
Die Verbindung schlug fehl,
handshake_failure
nachdem dieServerHello
erfolgreich beendet wurde, aber bevor der Datenstrom gestartet wurde.Es gab keine eindeutige Fehlermeldung, die das Problem identifizierte. Der Fehler sah einfach so aus
Ich habe das Problem isoliert, indem ich es mit und ohne die
-Djsse.enableSNIExtension=false
Option " " versucht habequelle
Meins war ein
TLS
inkompatibler Versionsfehler.Zuvor habe
TLSv1
ich es geändert, umTLSV1.2
mein Problem zu lösen.quelle
Ich verwende den http-Client com.google.api. Wenn ich mit einer internen Unternehmenswebsite kommuniziere, tritt dieses Problem auf, wenn ich versehentlich https anstelle von http verwendet habe.
quelle
Ich hatte ein ähnliches Problem. Ein Upgrade auf Apache HTTPClient 4.5.3 hat das Problem behoben.
quelle
Ugg! Es stellte sich heraus, dass dies für mich einfach ein Problem mit der Java-Version war. Ich habe den Handshake-Fehler mit JRE 1.6 erhalten und mit JRE 1.8.0_144 hat alles perfekt funktioniert.
quelle
Haftungsausschluss: Mir ist nicht bekannt, ob die Antwort für viele Menschen hilfreich sein wird, nur weil sie es könnte.
Ich habe diesen Fehler erhalten, als ich Parasoft SOATest zum Senden von Anforderungs-XML (SOAP) verwendet habe.
Das Problem war, dass ich den falschen Alias aus der Dropdown-Liste ausgewählt hatte, nachdem ich das Zertifikat hinzugefügt und authentifiziert hatte.
quelle
In meinem Fall kann die Website nur TLSv1.2 verwenden. und ich benutze Apache httpclient 4.5.6, ich benutze diesen Code und installiere jce, um dies zu lösen (JDK1.7):
jce
jdk7 http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
jdk 8 http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
Code:
quelle
So beheben Sie Fehler aus Sicht des Entwicklers (Punkt 1) und des Systemadministrators (Punkt 2 und 3):
-Djavax.net.debug=ssl:handshake:verbose
.sudo apt install ssldump
oder kompilieren Sie aus dem Quellcode, indem Sie diesem Link folgen , wenn Sie dies beobachtenUnknown value
beim Ausführen des folgenden Schritts eine .sudo ssldump -k <your-private-key> -i <your-network-interface>
Beispiel für einen nicht funktionierenden Handshake des ssldump-Protokolls:
Beispiel für einen erfolgreichen Handshake des ssldump-Protokolls
Beispiel für ein nicht funktionierendes Java-Protokoll
quelle
In meinem Fall hatte ich ein Problem mit der Version 1.1. Ich habe das Problem leicht mit Locken reproduziert. Der Server unterstützte keine niedrigeren Versionen als TLS1.2.
Dies erhielt ein Handshake-Problem:
Mit Version 1.2 hat es gut funktioniert:
Auf dem Server wurde ein Weblogic ausgeführt, und durch Hinzufügen dieses Arguments in setEnvDomain.sh konnte TLSv1.1 verwendet werden:
quelle
Dieses Problem tritt aufgrund der Java-Version auf. Ich habe 1.8.0.231 JDK verwendet und diesen Fehler erhalten. Ich habe meine Java-Version von 1.8.0.231 auf 1.8.0.171 herabgesetzt. Jetzt funktioniert es einwandfrei.
quelle