Zum Inhalt springen

Client für den Zugriff auf einen SSL-gesicherten Webservice


Metaner

Empfohlene Beiträge

Hallo,

ich möchte einen SSL-gesicherten Webservice in eine bestehende Anwendung einbinden. Da ich bislang keine Erfahrung mit SSL hatte, habe ich mir mit diversen Codeschnipseln eine lauffähige Lösung "gebastelt". Dazu habe ich mir das öffentliche Zertifikat vom SSL gesicherten Server besorgt, mir einen Keystore mit dem Keytool erstellt und dort das öffentliche Zertifikat importiert. Soweit so gut.

Das Zertifikat des Servers wird jährlich geändert, so dass ich dieses Prozedere jährlich durchführen muss (neues öffentliches Zertifikat besorgen und in Keystore einlesen). Das bekomme ich hin ... aber wie ist es, wenn man die Funktion des Webservice an andere Anwender weitergeben möchte? Ich möchte nicht dem Anwender zumuten, dass dieser sich um die Aktualität des öffentlichen Zertifikates Gedanken machen muss oder gar sich mit Dingen wie Keystore (Keytool) beschäftigen muss.

So sieht meine derzeitige SSL-Implementierung für den Client aus:


...


KeyStore ks = KeyStore.getInstance("JKS");

char[] keypassword = "...mein Passwort ...".toCharArray();

ks.load(new FileInputStream("...Pfad zu meinem Keystore..."), keypassword);

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");

kmf.init(ks, keypassword);


TrustManager[] myTrustManagerTrustAll = new TrustManager[] { new X509TrustManager() {

	public java.security.cert.X509Certificate[] getAcceptedIssuers() {

		return null;

	}

	public void checkClientTrusted(

		java.security.cert.X509Certificate[] certs, String authType) {

	}

	public void checkServerTrusted(

		java.security.cert.X509Certificate[] certs, String authType) {

	}

} };


SSLContext customSSLContext = SSLContext.getInstance("SSL");

customSSLContext.init(kmf.getKeyManagers(), myTrustManagerTrustAll, new SecureRandom());


HttpsURLConnection.setDefaultSSLSocketFactory(customSSLContext.getSocketFactory());


...

Kann mir jemand sagen, ob

a) es auch einen anderen Weg gibt, mit dem man dynamisch zur Laufzeit (d. h. ohne manuell das öffentliche Zertifikat zu besorgen und ohne einen Keystore mittels Keytool zu administrieren) den SSL-Zugriff eines Clients realisieren kann und

B) wie dies dann aussehen könnte/müsste?

Ich erwarte hier keine vollständige Implementierung (wenn es sowas gibt dann nehme ich die natürlich gerne ;)) ... es wäre aber schön, wenn man mich mit den richtigen "Zauberwörtern" auf den richtigen Weg bringen könnte. Ich habe schon das Internet durchwühlt und die Java-Api durchschaut. Bin aber selbst auf keinen Lösungsansatz gekommen. :(

Gruß Jan

PS: Ich würde mich noch als "Java"-Frischling bezeichnen. Daher verzeiht mir bitte, falls ich hier eine unqualifizierte Frage gestellt haben sollte. :floet:

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo flashpixx,

vielen Dank für den Link. Ich will aber meine Frage vielleicht noch mal etwas anders stellen. Ich bin mir nicht sicher ob ich auf dem Holzweg bin ... aber vielleicht kann mir das jemand sagen.

Ich hatte an einen Mechanismus gedacht der dem bei Webservices ähnelt. Dort gibt es doch die Möglichkeit, vom Webserver die Beschreibung (WSDL) zum Webservice abzufragen. Gibt es nicht auch soetwas für öffentliche Zertifikate? Ich kenne doch den Server mit dem ich kommunizieren will ... kann ich von dem nicht "online" das aktuell gültige öffentliche Zertifikat abfragen um meine aktuelle Verbindung damit zu sichern/zu verschlüsseln? In diesem Fall bräuchte es nämlich idealerweise keinen Keystore.

Oder habe ich damit zu kurz gedacht? :floet:

Gruß Jan

PS: Bislang habe ich das öffentliche Zertifikat nur über den Webbrowser und dessen Funktion zum Export des Zertifikates bekommen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Oder habe ich damit zu kurz gedacht? :floet:

Ich denke schon, denn das Zertifikat ist ja dafür gedacht die Quelle zu validieren. Nehmen wir mal an, dass Du einfach das Zertifikat ausliest und immer Deinem Schlüsselbund hinzufügen würdest. Wenn nun jemand den Server kompromitiert und dort ein eigenes Zertifikat installiert, dann würdest Du es in Dein Schlüsselbund hinzufügen, ohne dass Du merkst, dass etwas nicht stimmt.

Im Grunde bieten Dir Zertifikate eben die Sicherheit, dass Du weißt mit wem Du kommunizierst. Wenn das Zertifikat eben nur 1 Jahr Gültigkeit hat, dann wird der Aussteller seinen Grund haben, das so zu machen. Aber im Grunde ist das für die Kommunikation irrelevant, denn Du brauchst nicht das Zertifikat des Servers, sondern nur das der CA. Über die PKI ergibt sich dann logischerweise die Sicherheit des einzelnen Zertifikates. Irgendeine Instanz signiert das Zertifikat und man kann nun anhand des Zertifikates prüfen, welche Instanz (CA) das war. Das Zertifikat der CA musst Du dann besitzen.

Überlege einmal Du müsstest alle Zertifikate besitzen die z.B. VeriSign ausgestellt hat. Die Zertifikate die VeriSign signiert verweisen eben auf das CA Zertifikat von VeriSign, d.h. der Browser bekommt ein VeriSign signiertes Zertifikat vorgelegt und hat in seinem Schlüsselbund das VeriSign-Zertifikat. Nun kann er überprüfen ob das ihm vorgelegte Zertifikat eben anhand der Signatur und seinem hinterlegten VeriSign Zertifikat korrekt ist

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich ging bei meinen Überlegungen immer davon aus, dass die SSL Verbindung in erster Linie der Verschlüsselung der Kommunikation zwischen beiden Rechnern dient. Aber Du hast natürlich Recht, dass diese Sicherheit nicht viel bringt, wenn die Vertrauenswürdigkeit des Zertifikates nicht geprüft wird. :rolleyes:

Wenn ich Dich richtig verstanden habe, brauche ich dann einen Keystore in dem das (Root-)Zertifikat ... in meinem Fall wurde das Zertifikat von VeriSign ausgestellt .... import ist. Ich gehe einmal davon aus, dass diese Root-Zertifikate nicht ablaufen bzw. sehr lange gültig sind.

Erfolgt die Prüfung des Zertifikates des Webservers dann durch die Implementierung der entsprechenden Prüfmethoden im TrustManager? Wie Du anhand meines Codeschnipsels erkennen kannst, habe ich damit nämlich noch nicht gearbeitet. ;)

Das öffentliche Zertifikat des Webservers ist demnach für mich als Entwickler insofern nur von Bedeutung, dass dieses von den Kommunikationskomponenten ermittelt werden und zur Prüfung dem TrustManager übergeben werden kann. Ob "ich" (bzw. die Anwendung) dann diesem Zertifikat vertraut hängt allein und ausschließlich von der Implementierung "meiner" Prüfungen ab?

Habe ich das richtig verstanden?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Aber Du hast natürlich Recht, dass diese Sicherheit nicht viel bringt, wenn die Vertrauenswürdigkeit des Zertifikates nicht geprüft wird.

ich grinse etwas :floet:

Ich gehe einmal davon aus, dass diese Root-Zertifikate nicht ablaufen bzw. sehr lange gültig sind.

So sollte es sein

Erfolgt die Prüfung des Zertifikates des Webservers dann durch die Implementierung der entsprechenden Prüfmethoden im TrustManager?

Ich muss hier etwas passen, da ich lange nicht mehr damit gearbeitet habe und ich meine Codes nicht finde. Ich meine mich aber erinnern zu können, dass das automatisch gemacht wird und man z.B. zusätzlich sagen kann, das z.B. abgelaufene Zertifikate trotzdem okay sind usw.

Auf die schnelle hab ich das noch gefunden: Java HTTPS Client Issues Open Sourcery

Ob "ich" (bzw. die Anwendung) dann diesem Zertifikat vertraut hängt allein und ausschließlich von der Implementierung "meiner" Prüfungen ab?

Im Grunde her ja. Du baust die Verbindung auf, holst das Zertifikat und prüfst es. Browser melden ja z.B. dass sie das Zertifikat bei fehlender CA nicht prüfen können und man kann als User entscheiden, ob man trotzdem weiter machen will.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke für den Link ... ich lese aber jetzt erst einmal hier: JavaTM Secure Socket Extension (JSSE) Reference Guide. Ich habe nämlich das Gefühl mehr Grundlagen zu brauchen. Je mehr ich aber lese, desto mehr habe ich das Gefühl nichts mehr zu verstehen. :P Vielleicht liegts aber auch an der Uhrzeit ... der Kopf ist wohl schon zu voll.

... Du baust die Verbindung auf, holst das Zertifikat und prüfst es. ...

Und wie holt man das Zertifikat? :confused: Ich hatte nach meinem letzten Post gedacht, dass das von der SSL-Implementierung in Java gemacht wird und mir als Entwickler das Zertifikat sozusagen auf dem "goldenen Tablett" präsentiert wird. Aber so einfach ist es dann wohl doch nicht?

PS: Zu meiner Entlastung vielleicht noch etwas. Bislang hatte ich lediglich mit Java Berührung, wenn es um die Einbindung von Webservices ging. Die WS die ich bislang eingebunden hatte, laufen nicht über SSL. Daher tue ich mich jetzt etwas schwerer. Für die Implementierung der WS benutze ich JAX-WS. Damit habe ich mir auch für die jetzige Aufgabe den entsprechenden WS-Stub erstellt. In der Vergangenheit brauchte ich mir bei den erstellten WS-Clients keine Gedanken um die Verbindungssteuerung machen ... das machte der Stub bzw. das Framework für mich.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nachdem ich nun eine Nacht über das gelesene schlafen konnte und heute den ein und anderen Artikel gelesen habe konnte ich mir eine Lösung basteln, die ganz ohne Keystore bzw. importiertes Server-Zertifikat auskommt. Mit der nachfolgenden Implementierung funktioniert der Zugriff auch:


TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

trustManagerFactory.init((KeyStore)null);

SSLContext customSSLContext = SSLContext.getInstance("SSL");

customSSLContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());

HttpsURLConnection.setDefaultSSLSocketFactory(customSSLContext.getSocketFactory());

Nur frage ich mich jetzt, ob der eingebundene TrustManager auch wirklich das Zertifikat validiert. Zieht der TrustManager jetzt zur Prüfung das Zertifikat des Root-CA (VeriSign) aus "cacerts" heran?

Hat jemand eine Idee, wie man soetwas testen kann? Oder gibt es sonstige Kritik an dieser Art der Implementierung? Irgendwie sieht das zu einfach aus. :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hat jemand eine Idee, wie man soetwas testen kann? Oder gibt es sonstige Kritik an dieser Art der Implementierung? Irgendwie sieht das zu einfach aus. :D

Danke für die Lösung. Ich würde es so lassen. Du kannst es doch einfach mal so probieren: Entferne alle VeriSign Zertifikate (vorher aber sichern) aus dem Zertifikatstamm. Dann sollte die Prüfung fehlschlagen.

Alternativ kannst Du Dir ja auch ein selbst signiertes Zertifikat mit eigener CA erzeugen und dann eben die CA nicht in den Stamm importieren.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Entferne alle VeriSign Zertifikate (vorher aber sichern) aus dem Zertifikatstamm. Dann sollte die Prüfung fehlschlagen.

Danke für den Tipp. Das hat funktioniert! Nachdem ich nun mit keytool alle VeriSign-Zertifikate entfernt habe, läuft meine Anwendung beim Zugiff auf eine Exception.

Exception in thread "main" com.sun.xml.internal.ws.client.ClientTransportException: HTTP transport error: 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

Das genügt mir als Beweis dafür, dass Java zur Validierung das zentral abgelegte Zertifikat von VeriSign verwendet.

Hatte vor paar Tagen noch gedacht, dass die Lösung viel komplexer und aufwendiger sein würde. Aber so ist es natürlich auch gut. :)

@flashpixx: Vielen Dank!

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...