{"id":636,"date":"2021-08-19T16:20:43","date_gmt":"2021-08-19T16:20:43","guid":{"rendered":"https:\/\/www.cssec.de\/blog\/?p=636"},"modified":"2021-08-19T16:54:45","modified_gmt":"2021-08-19T16:54:45","slug":"https-abrufe-mit-java","status":"publish","type":"post","link":"https:\/\/www.cssec.de\/blog\/2021\/08\/19\/https-abrufe-mit-java\/","title":{"rendered":"HTTPS-Abrufe mit Java"},"content":{"rendered":"<p>Hallo da drau\u00dfen,<\/p>\n<p>gerade musste ich wieder einige Zeit lang schwitzen, weil bei meinem Cutworks-Projekt nach einer (vergessenen) SSL-Zertifikatserneuerung pl\u00f6tzlich eine essentielle Funktion ausgefallen und mit einer IOException\/SSL Handshake-Exception den Dienst verweigerte.<br \/>\nNach einigem Suchen, habe ich zumindest die Stelle gefunden, an der das ganze passiert.<\/p>\n<p>Kurz als Hintergrund: In dem Shop wird eine Fremdkomponente \u00fcber ein iframe integriert. Dieses iframe stellt eine Komponente bereit, mit der man Dinge auf einfache Weise konstruieren kann, sozusagen so eine Art Mini-CAD. Ist der Benutzer fertig wird durch einen Button-Druck au\u00dferhalb des iframe ein Server-Aufruf generiert, der Modell-Daten der externen Komponente abruft und entsprechend in interne Datenstrukturen umwandelt. Dabei erfolgt ein Aufruf einer externen URL direkt im Java-Server-Code \u00fcber https.<br \/>\nGenau dieser Server-Call warf nach Umstellung des Zertifikats eine Fehlermeldung und zwar (gek\u00fcrzt):<\/p>\n<p>javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target<\/p>\n<p>Der Aufruf der URL erfolgt im gro\u00dfen und ganzen mit Bordmitteln von Java, \u00fcber URL, HttpURLConnection und entsprechenden Streams, die dann abgefangen und umgewandelt werden. Hier mal ein entsprechendes Code-Snippet dazu:<\/p>\n<pre lang=\"java\">import java.io.BufferedReader;\r\nimport java.io.IOException;\r\nimport java.io.InputStream;\r\nimport java.io.InputStreamReader;\r\nimport java.net.HttpURLConnection;\r\nimport java.net.URL;\r\nimport org.apache.commons.io.IOUtils;\r\n\r\npublic class TestAbruf {\r\n\r\n public static void main(String[] args) {\r\n    String data = null;\r\n    try {\r\n       URL url = new URL(args[0]);\r\n       HttpURLConnection connection = (HttpURLConnection) url.openConnection();\r\n       connection.setRequestMethod(\"GET\");\r\n       connection.connect();\r\n       InputStream is = connection.getInputStream();\r\n       BufferedReader reader = new BufferedReader(new InputStreamReader(is));\r\n       data = IOUtils.toString(reader);\r\n       System.out.println(data);\r\n    }\r\n    catch  (IOException e) {\r\n       e.printStackTrace();\r\n    }\r\n }\r\n}\r\n<\/pre>\n<p>Ich habe den Code etwas abgewandelt, damit man das ganze relativ einfach direkt \u00fcber ein Mini-Tool aufrufen kann &#8211; dieser gibt dann einfach den Inhalt aus, der \u00fcber das Get geliefert wird. Soweit, so gut. Im Shop werden die Daten dann entsprechend weiter verarbeitet, der Inhalt ist eigentlich ein XML, dass dann geparst und in ein entsprechendes Modell umgewandelt wird.<br \/>\nAm Ende tut das aber nichts zur Sache. Bis heute morgen hat das ganze noch funktioniert, bis gegen Mittag das SSL-Zertifikat des Servers ung\u00fcltig wurde und ich eine Aktualisierung des Zertifikats auf dem entsprechenden Server eingespielt habe.<br \/>\nObwohl ich das entsprechend gemacht hatte, lief die Methode immer in die Exception hinein.<\/p>\n<p>Ein Aufruf der entsprechenden URL im Browser funktioniert aber &#8211; also musste das irgendetwas java-seitiges sein, dass da kaputt ist. Nach einigem \u00dcberlegen und Web-Suche kam ich auf den Trichter, dass Java m\u00f6glicherweise die Zertifikate entsprechend selbst verwaltet und das (neue) Zertifikat dann (noch) nicht kennt.<br \/>\nDie Suche ergab dann, dass es tats\u00e4chlich im JRE-Verzeichnis des Servers (bzw. des entsprechenden Rechners) im Unterverzeichnis <strong>lib\\security <\/strong>den Keystore <strong>cacerts<\/strong> gibt, in dem Java seine &#8222;trusted&#8220; Zertifikate hinterlegt.<br \/>\nDas neue Zertifikat vom Server muss dort hinterlegt werden, erst dann akzeptiert Java eine URL-Verbindung zu dem entsprechenden Server.<br \/>\nHier mal die Anleitung, wie ihr das entsprechend durchf\u00fchrt:<\/p>\n<ol>\n<li>ihr ben\u00f6tigt die Zertifikatsdatei (cer\/pem), die ihr entweder direkt bei der Erstellung des Zertifikats oder \u00fcber Euren Browser unter den Zertifikatsinformationen herunterladen k\u00f6nnt.<\/li>\n<li>\u00f6ffnet eine Kommandozeile als Administrator (bzw. root-shell unter Linux oder macOS)<\/li>\n<li>wechselt in das Verzeichnis des JDK \/ JRE auf eurem Rechner \/ Server\n<ol>\n<li style=\"list-style-type: none;\">\n<pre>cd \/D C:\\Program Files\\AdoptOpenJDK\\jdk-8.0.232.09-hotspot\\jre\\lib\\security<\/pre>\n<p>In meinem Fall habe ich eine AdoptOpenJDK 8 installiert, welches in dem oben genannten Verzeichnis installiert ist. Wechselt entsprechend Eurer Umgebung in das richtige Verzeichnis. Wichtig hierbei ist, wenn ihr ein JDK habt, dass ihr in den Unterordner jre\\lib\\security wechselt und nicht direkt in den lib-Ordner des JDK.<\/li>\n<\/ol>\n<\/li>\n<li>mit dem Keytool (im bin-Ordner der Java-Installation) k\u00f6nnt ihr dann das entsprechende Zertifikat importieren:\n<pre>keytool -keystore cacerts -import -alias mein_server -file C:\\Verzeichnis\\ssl\\meinserver_ssl_certificate.cer<\/pre>\n<p>Hinter alias k\u00f6nnt ihr einen beliebigen Namen einsetzen, \u00fcber den ihr Euer Zertifikat finden k\u00f6nnt. C:\\Verzeichnis\\ssl\\meinserver_ssl_certificate.cer ersetzt ihr entsprechend durch den Dateipfad der entsprechenden Zertifikatsdatei.<\/li>\n<li>Bei Abschicken des keytool-Kommandos wird ein Kennwort verlangt. Solltet ihr wie ich auch ein AdoptOpenJDK installiert haben, lautet das Kennwort standardm\u00e4\u00dfig: <strong>changeit<\/strong><\/li>\n<\/ol>\n<p>Sobald diese Schritte erfolgt sind, m\u00fcsst ihr, wenn ihr das ganze z.B. wie ich aus dem Tomcat oder einem anderen java-basierten Application-Server aufruft, den Server neu starten, nur so werden die \u00c4nderungen aktiv und der Aufruf funktioniert wieder.<\/p>\n<p>Ich bin mal gespannt, ob ich das n\u00e4chstes Jahr wieder machen muss, oder ob das dann besser funktioniert.<br \/>\nIn dem Sinne, bis bald.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hallo da drau\u00dfen, gerade musste ich wieder einige Zeit lang schwitzen, weil bei meinem Cutworks-Projekt nach einer (vergessenen) SSL-Zertifikatserneuerung pl\u00f6tzlich eine essentielle Funktion ausgefallen und mit einer IOException\/SSL Handshake-Exception den Dienst verweigerte. Nach einigem Suchen, habe ich zumindest die Stelle gefunden, an der das ganze passiert. Kurz als Hintergrund: In dem Shop wird eine Fremdkomponente [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":638,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/www.cssec.de\/blog\/wp-json\/wp\/v2\/posts\/636"}],"collection":[{"href":"https:\/\/www.cssec.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cssec.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cssec.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cssec.de\/blog\/wp-json\/wp\/v2\/comments?post=636"}],"version-history":[{"count":4,"href":"https:\/\/www.cssec.de\/blog\/wp-json\/wp\/v2\/posts\/636\/revisions"}],"predecessor-version":[{"id":648,"href":"https:\/\/www.cssec.de\/blog\/wp-json\/wp\/v2\/posts\/636\/revisions\/648"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cssec.de\/blog\/wp-json\/wp\/v2\/media\/638"}],"wp:attachment":[{"href":"https:\/\/www.cssec.de\/blog\/wp-json\/wp\/v2\/media?parent=636"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cssec.de\/blog\/wp-json\/wp\/v2\/categories?post=636"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cssec.de\/blog\/wp-json\/wp\/v2\/tags?post=636"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}