WS-Security mit Apache Axis

Axis sicher

Thilo Frotscher

Sichere Web Service-Anwendungen sind nicht mehr nur graue Theorie. Nachdem in [1] die Grundlagen von WS-Security eingehend erläutert wurden, soll nun die praktische Umsetzung anhand eines einfachen Beispiels verdeutlicht werden. Dieser Artikel ist ein gekürzter Vorabdruck des Kapitels Web Services und Sicherheit aus dem Buch Java Web Services mit Apache Axis, an der Autor gemeinsam mit vier weiteren derzeit arbeitet. Der Erscheinungstermin ist für Anfang 2004 geplant. Zum Verständnis der Beispiele setzt dieses Kapitel Kenntnisse über die Programmierung von Message Handlern voraus, da diese in einem früheren Kapitel des Buches erläutert werden.

Wenn WS-Security in Java-Anwendungen zum Einsatz kommen soll, wäre es natürlich schön, wenn auch hierfür eine Implementierung zur Verfügung stünde, welche sich um die entsprechenden Modifikationen einer SOAP-Nachricht kümmert, sodass der Entwickler diese mit Hilfe weniger API-Aufrufe verschlüsseln und signieren kann. Ohne eine solche Implementierung von WS-Security müssen Entwickler einige Zeilen mehr programmieren. Aber immerhin besteht ja die Möglichkeit, auf eine der verschiedenen Implementierungen von XML Encryption und XML Signature zurück zu greifen.

Zu dem Zeitpunkt, an dem dieser Text geschrieben wurde, stand lediglich eine einzige (Teil-) Implementierung von WS-Security für Java öffentlich zur Verfügung. Sie stammt von VeriSign und wurde für das im folgenden Abschnitt beschriebene Beispiel verwendet. In Zukunft sind aber weitere Implementierungen zu erwarten, und wenn dieses Buch erscheint ist das Angebot möglicherweise schon deutlich größer. So gibt es etwa bei Sourceforge ein Projekt namens Axis-WSSE, das jedoch noch ganz am Anfang steht und bisher lediglich Username Tokens unterstützt. Deutlich vielversprechender ist dagegen, dass im Oktober mit WSS4J eine WS-Security-Implementierung in das Axis-Projekt aufgenommen wurde, die jedoch ebenfalls noch längst nicht fertig gestellt ist. Somit ist aber zu erwarten, dass die kommende Axis-Version 1.2 die WS-Security-Spezifikation von Haus aus unterstützt.

An Bibliotheken, die in eigenen Anwendungen verwendet werden können, gibt es also bislang nur ein sehr mageres Angebot. Unabhängig davon unterstützen allerdings einige kommerzielle Lösungen wie etwa Systinets WASP Server 4.6 oder GLUE 4.1 (in der Professional Version) von The Mind Electric die WS-Security-Spezifiktation zumindest teilweise. Für andere Programmiersprachen und Plattformen gibt es übrigens auch schon Implementierungen. So ist von RSA eine Implementierung in C namens BSAFE Secure WS erhältlich, und für die .NET-Plattform veröffentlichte Microsoft ein Paket namens Web Service Enhancements 2.0.

Im Folgenden wird anhand eines Beispiels illustriert, wie mit Hilfe des Trust Services Integration Kit (TSIK) von Verisign und der separat erhältlichen WS-Security-Implementierung des gleichen Herstellers auf einfache Weise Message Handler für Axis-Anwendungen implementiert werden können, die dafür sorgen, dass SOAP-Nachrichten verschlüsselt und signiert werden.

Vorbereitungen

Zu erst sollte sichergestellt werden, dass ein Java SDK der Version 1.4.x installiert ist. Handelt es sich dabei um das SDK von Sun, so ergibt sich das Problem, das die darin enthaltene Implementierung der JCE (Java Cryptography Extension) keine Unterstützung für den RSA-Algorithmus enthält. Da dieser Algorithmus aber in vielen Fällen zum Einsatz kommt, wird eine andere JCE-Implementierung benötigt, die zusätzlich zu installieren ist. Unter anderem bietet IBM eine solche Implementierung an. Die entsprechende Bibliothek hat den Namen IBMJCEProvider.jar (manchmal auch komplett klein geschrieben) und wird unter anderem mit IBMs WebSphere SDK for Web Services (WSDK) und mit dem Emerging Technologies Toolkit (ETTK) ausgeliefert, die beide kostenlos heruntergeladen werden können. Die Bibliothek befindet sich jeweils in einer Verzeichnisstruktur namens libext. Je nach Version wird eventuell auch die Bibliothek ibmjlog.jar benötigt. Um die JCE-Implementierung von IBM einsetzen zu können, sind zwei Schritte nötig. Als erstes sollte die Datei IBMJCEProvider.jar in das Erweiterungsverzeichnis der Laufzeitumgebung (JRE) von Sun kopiert werden. Unter Windows würde das in etwa so aussehen:

copy IBMJCEProvider.jar [Sun_JRE_HOME]jrelibext

Anschließend ist die Sicherheitskonfiguration der Sun JRE anzupassen, die sich in der Datei [Sun_JRE_HOME]jrelibsecurityjava.security befindet. Hier muss die soeben kopierte Bibliothek von IBM als so genannter Security Provider bekannt gemacht werden. Die entsprechende Stelle in der Konfigurationsdatei sieht typischerweise so aus:

security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
security.provider.3=com.sun.rsajca.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider

Diese Zeilen sind wie folgt anzupassen:

security.provider.1=sun.security.provider.Sun
security.provider.2=com.ibm.crypto.provider.IBMJCE
security.provider.3=com.sun.net.ssl.internal.ssl.Provider
security.provider.4=com.sun.rsajca.Provider
security.provider.5=sun.security.jgss.SunProvider

Weiterhin wird natürlich das bereits erwähnte TSIK von VeriSign benötigt [2], sowie die separat erhältliche Implementierung von WS-Security [3]. Die beiden Bibliotheken tsik.jar und ws-security.jar sind in den Java Classpath aufzunehmen. Außerdem sollten Sie in das Bibliotheksverzeichnis der Axis-Installation kopiert werden, also typischerweise nach [tomcat_home]webappsaxisWEB-INFlib.

Wichtiger Hinweis: Vor dem Einsatz des TSIK und der WS-Security-Implementierung von VeriSign – insbesondere im produktiven Umfeld oder kommerziellen Einsatz – sind unbedingt gegebenenfalls bestehende oder abzuschließende Lizenzbestimmungen zu beachten! Nach momentanem Stand ist die WS-Security-Implementierung Open Source. Sie basiert jedoch auf dem TSIK, welches für kommerzielle Anwendungen als Teil des VeriSign Trust Gateway zu lizenzieren ist.

Als nächstes werden noch zwei so genannte Keystores benötigt – kleine Mini-Datenbanken, in denen Schlüssel und zugehörige X.509-Zeritifikate gespeichert werden. Die Keystores können mit einem Werkzeug namens keytool erzeugt und verwaltet werden, welches zusammen mit dem JDK ausgeliefert wird. Das folgende Batch-Skript erzeugt sowohl für den Client als auch für den Server jeweils ein asymmetrisches Schlüsselpaar und einen eigenen Keystore. Der Keystore des Clients enthält dessen eigenes Schlüsselpaar, sowie ein Zertifikat mit dem öffentlichen Schlüssel des Servers. Im Keystore des Servers sind das Schlüsselpaar des Servers, sowie ein Zertifikat mit dem öffentlichen Schlüssel des Clients enthalten. Für Testzwecke reicht dieses Vorgehen, in echten Anwendungen werden die Zertifikate natürlich meist von vertrauenswürdigen Instanzen ausgestellt (Listing 1). Sehr ausführliche Informationen zu keytool befinden sich in der Dokumentation des Java SDK, welche unter java.sun.com/docs/ eingesehen und heruntergeladen werden kann.

Listing 1

@echo off
echo Create RSA key pair for the client...
keytool -genkey -alias Client -keyalg RSA
-dname "CN=Client, O=JavaMagazin, C=DE"
-keypass keyPwd -keystore keystore_client
-storepass storePwd -storetype JCEKS

echo Copy client certificate to server's keystore...
keytool -export -alias Client -file foo.cer
-keystore keystore_client -storepass storePwd
-storetype JCEKS
keytool -import -noprompt -alias Client -file foo.cer
-keystore keystore_server -storepass storePwd
-storetype JCEKS
del foo.cer

echo Create RSA key pair for the server...
keytool -genkey -alias Server -keyalg RSA
-dname "CN=Server, O=JavaMagazin, C=DE"
-keypass keyPwd -keystore keystore_server
-storepass storePwd -storetype JCEKS

echo Copy server certificate to client's keystore...
keytool -export -alias Server -file foo.cer
-keystore keystore_server -storepass storePwd
-storetype JCEKS
keytool -import -noprompt -alias Server -file foo.cer
-keystore keystore_client -storepass storePwd
-storetype JCEKS
del foo.cer

Nach dem Ausführen der Batch-Datei befinden sich im Arbeitsverzeichnis die beiden Dateien keystore_client und keystore_server. Nun kann es daran gehen, die Message Handler für Axis zu programmieren.

Implementierung eines Axis-Handlers für WS-Security

Für unser Beispiel sollen zwei Handler erstellt werden: Der ClientSecurityHandler ist dafür verantwortlich, alle SOAP-Nachrichten eines Clients an einen Web Service zu verschlüsseln und zu signieren. Der ServerSecurityHandler entschlüsselt eingehende Nachrichten und prüft deren Signatur. Gewisse Funktionalitäten sind in beiden Handlern identisch, weshalb diese in eine abstrakte Superklasse namens AbstractSecurityHandler ausgelagert werden. Im Detail handelt es sich dabei um das Laden eines Keystores und um die dynamische Erzeugung eines symmetrischen Triple-DES Schlüssels (Listing 2).

Listing 2

package de.javamagazin.store;

import java.io.FileInputStream;
import java.security.*;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.components.logger.LogFactory;
import org.apache.commons.logging.Log;

public abstract class AbstractSecurityHandler extends
BasicHandler {
protected KeyStore keyStore = null;
protected Log log =
LogFactory.getLog(getClass().getName());

protected void loadKeyStore(String filename,
char[] keyStorePasswd) {
try {
if ((filename == null) || (filename.equals(""))) {
log.error("No keystore configured for
security handler!");
return;
}

keyStore = KeyStore.getInstance("JCEKS");
keyStore.load(new FileInputStream(filename),
keyStorePasswd);
log.info("ClientSecurityHandler: Keystore
successfully loaded.");
} catch (Exception e) {
log.error("Exception while initializing security
handler: " + e.getMessage());
keyStore = null;
}
}

protected Key createTripleDESKey() throws
GeneralSecurityException {
// generate random bytes
byte[] rb = new byte[24];
SecureRandom.getInstance("SHA1PRNG").nextBytes(rb);

// create TripleDES key
DESedeKeySpec keySpec = new DESedeKeySpec(rb);
Key myKey = SecretKeyFactory.getInstance("DESede").
generateSecret(keySpec);
return myKey;
}
}

Bis hierhin wurden ausschließlich Java-Bordmittel verwendet, sowie einige Handler- und Logging-Funktionalität aus der Axis-Bibliothek. Der Handler für die Client-Seite wird nun also von dieser abstrakten Klasse abgeleitet und soll alle Nachrichten verschlüsseln und signieren. Zu diesem Zweck muss natürlich zunächst der entsprechende Keystore geladen werden, was am besten in der Methode init geschieht. Der Dateiname des Keystore sollte über den Deployment Descriptor konfigurierbar sein und wird daher mit der Methode getOption ausgelesen (Listing 3).

Listing 3

package de.javamagazin.store;

import java.io.*;
import java.security.Key;
import java.security.cert.X509Certificate;
import javax.xml.transform.stream.StreamSource;

import com.verisign.messaging.WSSecurity;
import com.verisign.xmlenc.AlgorithmType;
import com.verisign.xmlsig.KeyInfo;
import com.verisign.xmlsig.SigningKey;
import com.verisign.xmlsig.SigningKeyFactory;

import org.apache.axis.*;
import org.apache.axis.utils.XMLUtils;
import org.w3c.dom.Document;

public class ClientSecurityHandler extends
AbstractSecurityHandler {
public void init() {
log.info("ClientSecurityHandler: Initialiazing...");
String filename = (String)getOption("keystore");
loadKeyStore(filename, "storePwd".toCharArray());
}

In der Methode invoke muss zunächst sichergestellt werden, dass der Keystore auch richtig geladen wurde. Falls ja, wird über das MessageContext-Objekt, welches die Axis Engine der Methode übergibt, zunächst auf die Request-Nachricht zugegriffen. Der in Ihr enthaltene SOAP Envelope muss in ein Document-Objekt umgewandelt werden, da die Implementierung von VeriSign mit dieser Klasse arbeitet. Anschließend kann das Document-Objekt zur Verschlüsselung und Signierung an die (noch zu implementierende) Methode signAndEncrypt übergeben werden. Schließlich muss das signierte und verschlüsselte Document-Objekt, also der SOAP-Envelope, als neuer Inhalt der Request-Nachricht gespeichert werden. Dies ginge eigentlich viel einfacher, indem statt der StreamSource eine DOMSource verwendet wird. Aufgrund eines Bugs funktioniert dieses Vorgehen jedoch leider nicht richtig (Listing 4).

Listing 4

public void invoke(MessageContext msgCtx) throws
AxisFault {
if (keyStore==null)
throw new AxisFault("ClientSecurityHandler:
key store not initialized");
try {
Message msg = msgCtx.getRequestMessage();
Document doc = msg.getSOAPEnvelope().getAsDocument();

signAndEncrypt(doc);

StreamSource s = new StreamSource(
new StringReader(XMLUtils.DocumentToString(doc)));

msg.getSOAPPart().setContent(s);

} catch (Exception e) {
throw new AxisFault("Exception in
ClientSecurityHandler: " + e.getMessage());
}
}

Nun fehlt für den ClientSecurityHandler nur noch die Methode signAndEncrypt, welche die eigentliche Kernaufgabe übernimmt. Hier wird ausführlich Gebrauch von VeriSigns TSIK gemacht. Interessierte Entwickler wenden sich bitte an die Dokumentation des TSIK.

Zunächst ist der private Schlüssel des Clients aus dem Keystore zu laden. Er wird zum Signieren der SOAP-Nachricht verwendet. Die Methode getKey liefert ein Key-Objekt zurück, welches mit Hilfe der Klasse SigningKeyFactory in einen SigningKey umgewandelt werden muss. Anschließend wird für den Schlüssel noch eine KeyInfo erzeugt, die ein X.509-Zertifikat mit dem zugehörigen öffentlichen Schlüssel enthält. Es kann auf Seiten des Empfängers verwendet werden, um die Signatur zu überprüfen.

Als nächstes müssen die nötigen Daten für die Verschlüsselung zusammengestellt werden. Hierzu wird zunächst ein symmetrischer Triple-DES-Schlüssel erzeugt, mit dem die SOAP-Nachricht verschlüsselt werden soll. Er wird zusammen mit der verschlüsselten Nachricht zum Empfänger geschickt. Dies macht natürlich nur Sinn, wenn der Triple-DES Schlüssel zuvor selbst verschlüsselt wird. Hierzu wird der öffentliche Schlüssel des Servers eingesetzt, weshalb im letzten Vorbereitungsschritt noch das Zertifikat des Servers (mit dessen öffentlichen Schlüssel) aus dem Keystore geladen wird. Schließlich wird eine Instanz von VeriSigns WS-Security Implementierung benötigt. Sie enthält eine Methode, die ebenfalls signAndEncrypt heißt. Ihr sind die zu bearbeitende SOAP-Nachricht, einige Angaben zu den zu verwendenden Algorithmen, sowie die soeben gesammelten Schlüssel und KeyInfo-Objekte zu übergeben. Als Resultat ist die übergebene SOAP-Nachricht nun verschlüsselt und signiert (Listing 5).

Listing 5

private void signAndEncrypt(Document soapMsg) throws
Exception {
log.info("ClientSecurityHandler: Encrypting and
signing the SOAP request...");
// use client's private key as the signing key
Key privateKeyClient = keyStore.getKey("Client",
"keyPwd".toCharArray());
SigningKey signingKey =
SigningKeyFactory.makeSigningKey(privateKeyClient);

// create key info for the signing key
KeyInfo signingKeyInfo = new KeyInfo();
signingKeyInfo.setCertificate(
(X509Certificate)keyStore.getCertificate("Client"));

// create a new symmetric data encryption key
Key dataEncKey = createTripleDESKey();

// get server's public key for encryption of the
// symmetric data encryption key
Key keyEncKey =
keyStore.getCertificate("Server").getPublicKey();
KeyInfo encryptingKeyInfo = null;

WSSecurity wsse = new WSSecurity();
wsse.signAndEncrypt(soapMsg, signingKey,
signingKeyInfo, dataEncKey,
AlgorithmType.TRIPLEDES,
keyEncKey, AlgorithmType.RSA1_5,
encryptingKeyInfo);
log.info("ClientSecurityHandler: Done.");
}
} // end class ClientSecurityHandler

Wie sieht nun der Handler für die Server-Seite aus? Die Methode init kann mehr oder weniger ähnlich ausfallen. Auch auf der Server-Seite sollte der Dateiname des Keystore über den Deployment Descriptor zu konfigurieren sein (Listing 6).

Listing 6

package de.javamagazin.store;

import java.io.*;
import java.security.Key;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.Collections;
import javax.xml.transform.stream.StreamSource;

import com.verisign.messaging.MessageValidity;
import com.verisign.messaging.WSSecurity;

import org.apache.axis.*;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.message.SOAPHeaderElement;
import org.apache.axis.utils.XMLUtils;
import org.w3c.dom.Document;
import org.xmltrustcenter.verifier.SimpleTrustVerifier;

public class ServerSecurityHandler extends
AbstractSecurityHandler {

public static final String WSSE_URI =
"http://schemas.xmlsoap.org/ws/2002/07/secext";
public static final String SECURITY = "Security";

public void init() {
log.info("ServerSecurityHandler: Initialiazing...");
String filename = (String)getOption("keystore");
loadKeyStore(filename, "storePwd".toCharArray());
}

In der Methode invoke muss auf Seiten des Servers im Unterschied zum Client natürlich eine Methode aufgerufen werden, welche die SOAP-Nachricht entschlüsselt und die Signatur überprüft. Außerdem ist es wichtig, den SOAP-Header namens Security anschließend als verarbeitet zu kennzeichnen (Listing 7). Andernfalls meldet die Axis-Engine nach Durchlauf aller Handler einen Fehler, da der Security-Header zwingend verarbeitet werden muss (das Attribut mustUnderstand ist standardmäßig auf den Wert 1 gesetzt).

Listing 7

public void invoke(MessageContext msgCtx) throws
org.apache.axis.AxisFault {
if (keyStore==null)
throw new AxisFault("ServerSecurityHandler:
key store not initialized");
try {
Message msg = msgCtx.getRequestMessage();
Document doc = msg.getSOAPEnvelope().getAsDocument();

verifyAndDecrypt(doc);

StreamSource s = new StreamSource(new
StringReader(XMLUtils.DocumentToString(doc)));
msg.getSOAPPart().setContent(s);

// mark Security header as processed
SOAPHeaderElement secHeader = msg.getSOAPEnvelope().
getHeaderByName(WSSE_URI, SECURITY);
secHeader.setProcessed(true);

} catch (Exception e) {
throw new AxisFault("Exception in
ServerSecurityHandler: " + e.getMessage());
}
}

Als letztes fehlt nun noch die Methode verifyAndDecrypt, welche die Kernfunktionalität des ServerSecurityHandler enthält. Auch hier kommen die Klassen des TSIK zum Einsatz. Zunächst lädt die Methode das X.509-Zertifikat des Clients aus dem Keystore des Servers. Es enthält den Public Key des Clients, mit dessen Hilfe ein SimpleTrustVerifier initialisiert wird. Dieser wird später dafür verantwortlich sein, die Signatur des Clients zu überprüfen. Anschließend wird auch der Private Key des Servers aus dem Keystore geladen. Er wird benötigt, um den in der Nachricht enthaltenen symmetrischen Triple-DES-Key zu entschlüsseln, mit dem dann die eigentliche Nachricht selbst entschlüsselt werden kann. Die eigentliche Arbeit verrichtet wieder die Klasse WSSecurity von VeriSign, und zwar dieses Mal in Form einer Methode, die ebenfalls verifyAndDecrypt heißt. Sie liefert ein Array von MessageValidity-Objekten zurück, von denen jedes einzelne daraufhin zu testen ist, ob die Validierung der Nachricht erfolgreich war. Hat alles geklappt, enthält soapMsg am Ende wieder eine unverschlüsselte SOAP-Nachricht (Listing 8).

Listing 8

security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
security.provider.3=com.sun.rsajca.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider

Nachdem die beiden Handler implementiert wurden, müssen Sie noch in die Verarbeitungskette der Axis-Engine integriert werden. Hierfür sind zwei Deployment Descriptoren zu schreiben: einer für den Client und einer für den Web Service. Deployment Descriptoren für den Client heißen typischerweise client-config.wsdd. Sie müssen mindestens je einen Pivot-Handler für alle eingesetzten Transportmechanismen definieren. Für das hier beschriebene Beispiel wird der Deployment Descriptor ähnlich wie bei der Konfiguration eines Service um ein Element namens globalConfiguration erweitert, dessen Aufbau im Kapitel über Message Handler erläutert wurde (Listing 9).

Listing 9

security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
security.provider.3=com.sun.rsajca.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider

Um innerhalb eines Client-Programms einen bestimmten Deployment Descriptor zu laden, können die Schnittstelle EngineConfiguration bzw. die Klasse FileProvider verwendet werden. Ein Objekt der Klasse FileProvider wird mit dem absoluten Pfad zum Deployment Descriptor initialisiert und anschließend dem Konstruktor der Klasse Service übergeben. Über Service wird ein Call-Objekt erzeugt und dann wie gehabt fortgefahren.

security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
security.provider.3=com.sun.rsajca.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider

Der Deployment Descriptor für den Web Service enthält für Leser des Kapitels über Message Handler keine Überraschungen mehr, soll aber der Vollständigkeit halber nicht fehlen (Listing 10).

Listing 10

security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
security.provider.3=com.sun.rsajca.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider

Nun ist alles beisammen und die Handler können ausprobiert werden. Zuvor sollte nicht vergessen werden, die auf Seiten des Web Service benötigten Klassen AbstractSecurityHandler und ServerSecurityHandler ins Verzeichnis [tomcat_home]webappsaxisWEB-INFclasses zu kopieren, damit die Axis-Engine sie auch finden kann. Um zu kontrollieren, ob der Client auch wirklich verschlüsselte und signierte SOAP-Nachrichten an den Server schickt, kann beispielsweise der im Axis-Paket enthaltene TCP-Monitor verwendet werden.

Betrachtet man die versendeten Nachrichten, so fällt auf, dass die Signaturen jeweils über zwei Elemente errechnet werden, nämlich dem Body-Element der SOAP-Nachricht sowie dem Timestamp-Header, der von WS-Security eingefügt wurde. Der somit vor Manipulationen geschützte Timestamp bietet einen (begrenzten) Schutz gegen Replay-Attacken, da der Empfänger Duplikate erkennen kann. Ebenso ist zu beachten, dass die zur Verifikation der Signatur benötigten Schlüsselinformationen nicht im XML Signature-Element names KeyInfo enthalten sind, sondern das dieses auf das WS-Security Element BinarySecurityToken verweist.

Das hier beschriebene Beispiel ist recht einfach gehalten, um sich auf das wesentliche, nämlich den Einsatz von WS-Security, zu konzentrieren. Für echte Anwendungen gibt es eine Reihe von Ansätzen für Verbesserungen. So wird in der Regel gewünscht sein, dass nicht nur die SOAP-Nachrichten des Clients an den Web Service verschlüsselt und signiert werden, sondern auch die Antworten. Außerdem sollten die Passwörter für die privaten Schlüssel und Keystores keinesfalls als Klartext im Programmcode stehen – sie könnten beispielsweise auf einem LDAP-Server gespeichert werden. Was die Verwendung der Schlüssel betrifft, so benutzt der ServerSecurityHandler den Public Key des Absenders aus dem Keystore. Da das Zertifikat des Absenders aber in der Nachricht enthalten ist, könnte man auch den Public Key aus diesem Zertifikat verwenden. Dies hängt davon ab, ob man eventuell nur Zertifikaten vertrauen will, die sich im eigenen Keystore befinden. Und schließlich ist auch die Fehlerbehandlung sicherlich verbesserungswürdig. Die vorgestellte Lösung kann also als Startpunkt für eigene Experimente mit WS-Security dienen.

Thilo Frotscher ist freiberuflicher Systemarchitekt, Trainer und Berater mit den Schwerpunkten Java, Web Services, XML und Software-Architekturen. Neben der Mitarbeit in Projekten leitete er bereits etliche Schulungen und berichtet auf Fachkonferenzen über seine Erfahrungen. Gemeinsam mit anderen Autoren schreibt er gerade an einem Buch mit dem Titel Java Web Services mit Apache Axis. Kontakt: feedback@frotscher.com

Geschrieben von
Thilo Frotscher
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.