2009-05-20 1 views
6

In meiner Java-Anwendung muss ich mich mit demselben Host über SSL verbinden, aber jedes Mal ein anderes Zertifikat verwenden. Der Grund, warum ich verschiedene Zertifikate verwenden muss, ist, dass die entfernte Site eine Benutzer-ID-Eigenschaft verwendet, die in das Zertifikat eingebettet ist, um den Client zu identifizieren.Mehrere SSL-Client-Zertifikate in Java mit demselben Host verwenden

Dies ist eine Server-Anwendung, die auf 3 verschiedenen Betriebssystemen ausgeführt wird, und ich muss Zertifikate wechseln können, ohne den Prozess neu zu starten.

Another user schlug vor, mehrere Zertifikate in denselben Keystore zu importieren. Ich bin mir nicht sicher, ob mir das hilft, es sei denn, es gibt eine Möglichkeit, Java mitzuteilen, welches Zertifikat im Keystore verwendet werden soll.

Antwort

11

SSL kann dem Client Hinweise dazu geben, welches Zertifikat angezeigt werden soll. Diese möglicherweise können Sie einen Schlüsselspeicher mit mehreren Identitäten darin verwenden, aber leider verwenden die meisten Server diese Hinting-Funktion nicht. Daher wird es robuster, wenn Sie das Clientzertifikat angeben, das für jede Verbindung verwendet werden soll.

Hier ist Beispielcode zum Einrichten einer SSLContext mit angegebenen Identität und Trust Stores. Sie können diese Schritte wiederholen, um mehrere Kontexte zu erstellen, einen für jedes Clientzertifikat, das Sie verwenden möchten. Jeder SSLContext würde wahrscheinlich den gleichen Truststore verwenden, aber einen anderen Identitätsspeicher (der den einzelnen Clientschlüsseleintrag enthält, der in diesem Kontext verwendet werden soll).

Initialisieren Sie die Kontexte, die Sie einmal benötigen, und verwenden Sie für jede Verbindung das richtige Konnex. Wenn Sie mehrere Verbindungen herstellen, können Sie SSL-Sitzungen nutzen.

KeyManagerFactory kmf = 
    KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
kmf.init(identityStore, password); 
TrustManagerFactory tmf = 
    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
tmf.init(trustStore); 
SSLContext ctx = SSLContext.getInstance("TLS"); 
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 

Später Sie direkt einen Socket erstellen:

SSLSocketFactory factory = ctx.getSocketFactory(); 
Socket socket = factory.createSocket(host, port); 

Oder, wenn Sie die URL Klasse verwenden, können Sie die SSLSocketFactory angeben zu verwenden, wenn HTTPS-Anfragen machen:

Java 6 verfügt über eine zusätzliche API, die das Konfigurieren von Sockets nach Ihren Präferenzen für Cipher Suites usw. erleichtert.

+0

"Java 6 hat einige zusätzliche API, die es einfacher macht, Sockets nach Ihren Präferenzen für Cipher Suites zu konfigurieren" Können Sie mich auf weitere Dokumentation/Diskussion zu diesen Konfigurationen verweisen? – Tazzy531

+0

@ Tazzy531 - Java 6 hinzugefügt ['SSLParameters',] (http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/javax/net/ssl/class-use/SSLParameters. html), die Sie in einer einzigen Operation auf eine 'SSLEngine' oder eine neue' SSLSocket' setzen können. – erickson

0

Es gibt eine Lösung here für die dynamische Auswahl des Client-Zertifikats, das für die SSL-Authentifizierung von einem Axis Client verwendet wird.