Ein Modul, das ich unserer großen Java-Anwendung hinzufüge, muss sich mit der SSL-gesicherten Website eines anderen Unternehmens unterhalten. Das Problem ist, dass die Site ein selbstsigniertes Zertifikat verwendet. Ich habe eine Kopie des Zertifikats, um zu überprüfen, ob ich nicht auf einen Man-in-the-Middle-Angriff stoße, und ich muss dieses Zertifikat so in unseren Code integrieren, dass die Verbindung zum Server erfolgreich ist.
Hier ist der Grundcode:
void sendRequest(String dataPacket) {
String urlStr = "https://host.example.com/";
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setMethod("POST");
conn.setRequestProperty("Content-Length", data.length());
conn.setDoOutput(true);
OutputStreamWriter o = new OutputStreamWriter(conn.getOutputStream());
o.write(data);
o.flush();
}
Ohne zusätzliche Behandlung für das selbstsignierte Zertifikat stirbt dies bei conn.getOutputStream () mit der folgenden Ausnahme:
Exception in thread "main" 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
....
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
....
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Im Idealfall muss mein Code Java beibringen, dieses eine selbstsignierte Zertifikat für diesen einen Punkt in der Anwendung und nirgendwo anders zu akzeptieren.
Ich weiß, dass ich das Zertifikat in den Zertifizierungsstellenspeicher der JRE importieren kann, sodass Java es akzeptieren kann. Das ist kein Ansatz, den ich verfolgen möchte, wenn ich helfen kann. Es scheint sehr invasiv zu sein, auf allen Maschinen unserer Kunden ein Modul zu verwenden, das sie möglicherweise nicht verwenden. Es würde alle anderen Java-Anwendungen betreffen, die dieselbe JRE verwenden, und das gefällt mir nicht, obwohl die Wahrscheinlichkeit, dass eine andere Java-Anwendung jemals auf diese Site zugreift, gleich Null ist. Es ist auch keine triviale Operation: Unter UNIX muss ich Zugriffsrechte erhalten, um die JRE auf diese Weise zu ändern.
Ich habe auch gesehen, dass ich eine TrustManager-Instanz erstellen kann, die einige benutzerdefinierte Überprüfungen durchführt. Es sieht so aus, als ob ich möglicherweise sogar einen TrustManager erstellen kann, der in allen Fällen mit Ausnahme dieses einen Zertifikats an den echten TrustManager delegiert. Aber es sieht so aus, als würde TrustManager global installiert, und ich nehme an, dass dies alle anderen Verbindungen aus unserer Anwendung betreffen würde, und das riecht auch für mich nicht ganz richtig.
Was ist die bevorzugte, standardmäßige oder beste Methode, um eine Java-Anwendung für die Annahme eines selbstsignierten Zertifikats einzurichten? Kann ich alle oben genannten Ziele erreichen oder muss ich Kompromisse eingehen? Gibt es eine Option, die Dateien und Verzeichnisse und Konfigurationseinstellungen sowie wenig bis gar keinen Code umfasst?