2012-07-31 6 views
17

Ich baue einen einfachen App-Monitor, um eine unserer API-URLs abzurufen und uns eine E-Mail zu senden, wenn er keinen HTTP 200-Statuscode von der Antwort erhält (dies würde auf unsere API hinweisen) ist aus irgendeinem Grund nicht erreichbar).SSL-Fehler "Peer nicht authentifiziert" mit HttpClient 4.1

Ich bin mit Httpclient 4.1 (Dies ist wichtig, weil seine API stark von 3.x unterscheidet).

Unsere API mit SSL sicher ist jedoch eingeben:

http://example.com/our-api

in einem Web-Browser leitet Sie auf

https://example.com/our-api

Ohne verursacht Fehler.

Wenn Httpclient versucht, diese URL zu schlagen (http://example.com/our-api), schlägt es mit einer javax.net.ssl.SSLPeerUnverifiedException Ausnahme mit einer Meldung, die besagt:

Peer nicht

authentifiziert Ich sehe das viel für andere Menschen geschieht wie es durch this Post nachgewiesen wird (die auch einige Möglichkeiten bietet, dieses Problem zu umgehen - eine Lösung, die ich heute Abend tatsächlich versuchen werde zu implementieren).

Was dieser andere Beitrag (und die anderen ähnlichen dazu) nicht tun, erklärt, warum das überhaupt passiert! Also, anstatt zu fragen "Wie repariere ich das?" Ich dachte, ich würde fragen „warum ist das passiert?“ Bevor ich weiter mit einem der vorgeschlagenen Lösungen gehen aufschalten, ich würde gerne wissen, was das Problem ist, dass ich ;-)

+1

Könnten Sie den vollständigen Stack-Trace schreiben? –

+0

Es sollte beachtet werden, dass diese Nachricht auf seltsame Programmierung im HttpClient zurückzuführen sein muss. Es hätte einen früheren "Handshake-Fehler" von SSLException gegeben, und das hätte ausgelöst werden sollen. Offensichtlich wurde die Ausführung zu einem SSLSession.getPeerCertificate() -Aufruf fortgesetzt, der die einzige API ist, die die Ausnahme im Titel auslöst. – EJP

Antwort

24

zu beheben bin versucht, Wenn das Zertifikat des Servers selbst signiert ist, funktioniert dies wie vorgesehen und Sie müssen das Zertifikat des Servers in Ihren Keystore importieren.

Unter der Annahme, das Server-Zertifikat von einer bekannten CA signiert ist, dies geschieht, weil die Menge der CA-Zertifikate zur Verfügung zu einem modernen Browser viel größer als die begrenzte Menge ist, die mit dem JDK/JRE ausgeliefert wird.

Die EasySSL-Lösung, die Sie in einem der angegebenen Posts angeben, vergräbt den Fehler, und Sie wissen nicht, ob der Server über ein gültiges Zertifikat verfügt.

Sie müssen die richtige Stammzertifizierungsstelle in Ihren Keystore importieren, um das Zertifikat zu überprüfen. Es gibt einen Grund, warum Sie dies mit dem SSL-Standardcode nicht umgehen können, und das verhindert, dass Sie Programme schreiben, die sich so verhalten, als wären sie sicher, aber nicht.

+0

In den meisten Fällen sendet der SSL-Server die Kette bis zum Stammzertifikat, jedoch nicht darunter. Daher müssen Sie die gesamte Kette meistens nicht in den Keystore importieren. Sie sollten jedoch dem Stammzertifikat explizit vertrauen. –

+0

@owlstead ja, normalerweise müssen Sie nur die Root CA importieren; Antwort bearbeitet. –

+0

Ich importierte das Zertifikat (Base64-Version) in den Schlüsselspeicher unter "lib \ security \ cacerts", aber Java gibt immer noch den gleichen Fehler. Als ich es in den Windows-Speicher für vertrauenswürdige Zertifikate importierte, hörte chrome auf, Fehler zu geben. Aber wenn ich es mit Java Keytool gemacht habe, kann es immer noch keine Verbindung herstellen. – nurettin

6

Dies wird ausgelöst, wenn

... der Peer selbst nicht in der Lage war zu identifizieren (zum Beispiel, kein Zertifikat, das insbesondere wobei Cipher Suite verwendet, nicht Authentifizierung oder keine Peer-Authentifizierung nicht unterstützt war während SSL Handshake etabliert) wird diese Ausnahme ausgelöst.

Wahrscheinlich die Ursache dieser Ausnahme (wo ist der Stacktrace) wird Ihnen zeigen, warum diese Ausnahme ausgelöst wird. Höchstwahrscheinlich enthält der Standard-Keystore, der mit Java ausgeliefert wird, das Stammzertifikat der verwendeten TTP nicht (und vertraut nicht).

Die Antwort besteht darin, das Stammzertifikat (z. B. aus der SSL-Verbindung Ihres Browsers) abzurufen, es in die cacerts-Datei zu importieren und es unter Verwendung des vom Java JDK gelieferten Geräts keytool zu vertrauen. Andernfalls müssen Sie programmgesteuert einen anderen Vertrauensstellungsspeicher zuweisen.

0

Ich bin kein Java-Entwickler, sondern eine Java-App, um eine RESTful API zu testen. Um den Fehler zu beheben, musste ich die Zwischenzertifikate auf dem Webserver installieren, um den Fehler zu beheben. Ich benutzte Lighttpd, das ursprüngliche Zertifikat wurde auf einem IIS-Server installiert. Ich hoffe es hilft. Das waren die Zertifikate, die ich auf dem Server vermisst hatte.

  • ca.crt
  • UTNAddTrustServer_CA.crt
  • AddTrustExternalCARoot.crt
0
keytool -import -v -alias cacerts -keystore cacerts.jks -storepass changeit -file C:\cacerts.cer 
Verwandte Themen