17
AUTOR Fabian Fassott Orientation in Objects GmbH Veröffentlicht am: 27.11.2008 WEB SERVICES MITTELS USERNAMETOKEN SICHERN Die Authentifzierung von menschlichen Benutzern erfolgt üblicherweise per Passwort. Dieses Tutorial beschreibt, wie Web Services durch Passwortverfahren geschützt werden können. Dabei wird auf NetBeans, Metro und GlassFish zurückgegriffen. Java, XML, UML, XSLT, Open Source, JBoss, SOAP, CVS, Spring, JSF, Eclipse Trivadis Germany GmbH Weinheimer Str. 68 D-68309 Mannheim Tel. +49 (0) 6 21 - 7 18 39 - 0 Fax +49 (0) 6 21 - 7 18 39 - 50 www.oio.de [email protected] Web Services mit UsernameToken sichern ) Schulung ) ) Beratung ) ) Entwicklung ) ) Artikel )

Web Services mit UsernameToken sichern - OIO · WEB SERVICE MITTELS USERNAMETOKEN SICHERN Die wohl am weitesten verbreitete und beliebteste Authentifizierungsmethode für schützenswerte

  • Upload
    others

  • View
    12

  • Download
    0

Embed Size (px)

Citation preview

AUTOR

Fabian FassottOrientation in Objects GmbH

Veröffentlicht am: 27.11.2008

WEB SERVICES MITTELS USERNAMETOKEN SICHERN

Die Authentifzierung von menschlichen Benutzern erfolgt üblicherweise per Passwort.Dieses Tutorial beschreibt, wie Web Services durch Passwortverfahren geschütztwerden können. Dabei wird auf NetBeans, Metro und GlassFish zurückgegriffen.

Java, XML, UML, XSLT, Open Source, JBoss, SOAP, CVS, Spring, JSF, Eclipse

Trivadis Germany GmbH

Weinheimer Str. 68D-68309 Mannheim

Tel. +49 (0) 6 21 - 7 18 39 - 0Fax +49 (0) 6 21 - 7 18 39 - 50

www.oio.de [email protected]

Web Services mit UsernameToken sichern

) Schulung )

) Beratung )

) Entwicklung )

) A

rtik

el)

WEB SERVICE MITTELS USERNAMETOKEN SICHERN

Die wohl am weitesten verbreitete und beliebteste Authentifizierungsmethode für schützenswerte Ressourcen ist die Vergabe vonBenutzernamen samt zugehöriger Passwörter. Für Web Services existiert für den Bereich Sicherheit die Web Service Security-Spezifikation(WSS) [1]. Diese bietet die Möglichkeit, SOAP-Nachrichten zu verschlüsseln sowie deren Integrität zu bewahren. Mit WS-Security ist dieVerschlüsselung und Integrität von Daten somit unabhängig vom Transportprotokoll möglich (SSL). Zusätzlich definiert sie, wie aufsicherheitsrelevante Daten (Zertifikate, Kerberos-Tickets, Schlüssel) zu verweisen ist. WSS wird durch so genannte Profiles erweitert, dieeinen speziellen Sicherheitskontext abdecken. Für die Authentifizierung per Passwort existiert das UsernameTokenProfile [2]. Hauptgegenstanddes UsernameTokenProfiles ist das UsernameToken, welches im SOAP-Header zum Service übertragen wird. Beispiel 1 zeigt dessen Aufbau.

<UsernameToken wsu:Id="Example-1"><Username>...</Username><Password Type="...">...</Password><Nonce EncodingType="...">...</Nonce><Created>...</Created>

</UsernameToken>

Beispiel 1: Das UsernameToken-Element:

Unter Username wird der Benutzername angegeben, Password enthält je nach Wert des Type-Attributs entweder das Klartextpasswort oderden Hash-Wert des Klartextpassworts, Nonce und Created sollen Replay-Angriffe vermeiden, bei denen ein UsernameToken von einemAngreifer abgefangen und unbefugterweise von diesem selbst in SOAP-Nachrichten verwendet wird.

Replay-Attacke

Ein Angreifer könnte eine Nachricht samt UsernameToken abfangen und zu einem späteren Zeitpunkt erneut an den Service schicken.Durch das enthaltene UsernameToken wäre der Angreifer zur Nutzung des Services autorisiert. Um dies zu vermeiden, wird jedesUsernameToken mit einer eindeutigen Nummer versehen (Nonce). Der Service merkt sich diese Nummer und weist neu zugestellteUsernameTokens mit der gleichen Nummer ab. Um zu vermeiden, dass die Liste verwendeter Nummern immer weiter wächst, wird einZeitstempel (Created) in jedem UsernameToken übertragen. Nach Ablauf der angegebenen Zeit ist ein UsernameToken nicht mehr gültig.Somit können Nonces, deren Zeitstempel abgelaufen ist, bedenkenlos gelöscht werden.

Es ist nicht immer möglich, im Password-Element den Hash-Wert des Passworts zu übertragen, da der Service möglicherweise keinen Zugriffauf die Klartextpasswörter der Benutzer hat und somit nicht selbst deren Hash zum Vergleich berechnen kann. In solchen Fällen sollte dasKlartextpasswort im Password-Element stehen. Das zu übertragende UsernameToken ist dann mittels WS-Security zu verschlüsseln. Wiedies mit dem Web Service-Stack Metro [3] erzielt werden kann, wird im Folgenden beschrieben.

VORAUSSETZUNGEN

• GlassFish V2 UR2 [4] mit Metro 1.2 [5, 6] und GlassFish-Zertifikatupdate [7]

• NetBeans 6.1 [8]

• GlassFish V2 UR2 in NetBeans einrichten, wofür folgende Schritte nötig sind:

1. NetBeans 6.1 starten.

2. Services-Tab wählen -> Rechtsklick auf Servers->Add Server…-> Server: GlassFish V2, Name: GlassFish V2 UR2 -> Next-> PlatformLocation: Pfad zu installiertem GlassFish V2 UR2 angeben -> Next-> evt. Admin-Daten anpassen ->Finish

SERVICE-IMPLEMENTIERUNG

Um zu demonstrieren, wie ein Web Service mittels UsernameToken gesichert werden kann, muss dieser zunächst erstellt werden. Dabeiwird kein Wert auf eine anspruchsvolle Implementierung gelegt, es geht lediglich darum, einen Web Service zu erstellen, der dann gesichertwerden kann.

1. In NetBeans ist ein neues Projekt für den zu sichernden Web Service zu erstellen. File -> New Project -> Categories: Web und Projects:Web Application -> Next -> Project Name: UsernameTokenService -> Next -> Server: konfigurierten GlassFish-Server mit Metro 1.2auswählen -> Finish.

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 2 von 17www.oio.de [email protected]

Abbildung 1: Schritt 1: Projekt erstellen

2. Nach der Erstellung des Projektes, wird innerhalb dieses Projektes der zu schützende Web Service angelegt: Rechtsklick auf eben erstelltesProjekt-> New-> Other... -> Categories: Web Services und File Types: Web Service -> Next -> Web Service Name: UsernameTokenService,package: server -> Finish

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 3 von 17www.oio.de [email protected]

Abbildung 2: Schritt 2: Web Service erstellen

3. Das erstellte Grundgerüst des Web Services ist nun mit Leben zu füllen: Unter Projekt den Ordner Web Services expandieren undDoppelklick auf UsernameTokenService -> Wechsel in Source-Ansicht (befindet sich links oben im zentralen Fenster). Die Implementierungso ändern, dass sie Beispiel 2 entspricht.

package server;import javax.jws.WebMethod;import javax.jws.WebParam;import javax.jws.WebService;@WebService()public class UsernameTokenService{@WebMethod(operationName = "sayHello")public String sayHello(@WebParam(name = "name") String name){return "Hello " +name;

}}

Beispiel 2: Implementierung von UsernameTokenService

4. Der implementierte Web Service soll nun so gesichert werden, dass nur authentifizierte Benutzer ihn verwenden dürfen. Die Authentifizierungsoll per UsernameToken erfolgen. Dafür sind folgende Schritte nötig: Rechtsklick auf UsernameTokenService unter Web Services-Ordner-> Edit Web Service Attributes -> Haken bei Secure Service . Nun besteht die Möglichkeit, einen Sicherungsmechanismus (SecurityMechanism) auszuwählen. Um die Sicherung per UsernameToken zu erreichen, muss der entsprechende Wert ausgewählt werden-> SecurityMechanism: Username Authentication with Symmetric Key. Der abschließende Haken bei Use Development Defaults bewirkt, dass dieStandard-Schlüssel der GlassFish-Installation für die anzuwendenden kryptographischen Operationen zu verwenden sind. Welche Operationengenau ausgeführt werden, wird später erläutert (Client-Implementierung, Schritt 6).

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 4 von 17www.oio.de [email protected]

Abbildung 3: Schritt 4: Sichern des Services per UsernameToken

5. Der gesicherte Web Service ist abschließend auf GlassFish zu deployen: Rechtsklick auf Projekt -> "Undeploy and Deploy" wählen.

BENUTZER HINZUFÜGEN

Nachdem der Service deployed wurde, muss ein Benutzer für dessen Verwendung erstellt werden.

1. Zunächst muss der GlassFish-Server gestartet werden, sofern er nicht gestartet wurde. In NetBeans Services-Tab auswählen -> Serversexpandieren -> Rechtsklick auf GlassFish V2 UR2 -> Start.

2. Mittels Browser sich mit http://localhost:4848 verbinden. Standardbenutzername: admin, Standardpasswort: adminadmin.

3. Im linken Fenster Configuration -> Security -> Realms -> file, dann auf Manage Users im rechten Fenster klicken.

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 5 von 17www.oio.de [email protected]

Abbildung 4: Schritt 3: Unter dem Realm "File" einen neuen Benutzer hinzufügen.

4. Jetzt den Web Service-Benutzer erstellen: Auf New klicken -> User ID: client, Group List: leer lassen, New Password und Confirm NewPassword: client -> OK.

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 6 von 17www.oio.de [email protected]

Abbildung 5: Schritt 4: Erstellen des Benutzers für den Web Service

CLIENT-IMPLEMENTIERUNG

Nachdem der Web Service erstellt und ein zur Nutzung befugter Benutzer erstellt wurde, kann der Client implementiert werden. Dieser wirdals Standalone-Client erstellt, was wie folgt bewerkstelligt wird:

1. Das Client-Projekt erstellen: File -> New Project…-> Categories: Java und Projects: Java Application -> Next -> Project Name:UsernameTokenServiceSOClient, Create Main Class: client.Main -> Finish.

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 7 von 17www.oio.de [email protected]

Abbildung 6: Schritt 1: Erstellen des Client-Projekts

2. Den Web Service Client erstellen (GlassFish muss laufen und UsernameTokenService muss deployed sein): Rechtsklick auf erstelltesProjekt -> New -> Other… -> Categories: Web Services und File Type: Web Service Client -> Next -> WSDL URL:http://localhost:8080/UsernameTokenService/UsernameTokenServiceService?wsdl -> Finish

Hinweis: Die URL zur WSDL-Datei ergibt sich nach folgendem Muster:

Transportprotokoll des Web Service-Bindings://Rechnername:GlassFish-Port/ContextRoot des Web Service-War-Files (Standard:Projektname)/X?wsdl

X entspricht dabei standardmäßig dem Namen der Implementierungsklasse des Web Services plus dem Suffix Service. In unserem Falleheißt die Implementierungsklasse UsernameTokenService. Samt Suffix wird daraus dann UsernameTokenServiceService. X kann allerdingsauch frei gewählt werden. Hierfür muss ein Attribut der @WebService-Annotation der Implementierungsklasse genutzt werden. Durch dieAngabe von @WebService(serviceName="ABCService") wird aus dem X-Teil der WSDL-URL ABCService. Gleichzeitig bewirkt die Angabedieses Attributs, dass das name-Attribut des Service-Elements in der für den Web Service generierten WSDL-Datei auf ABCService gesetztwird. Diese Regeln gelten nicht nur für die WSDL-URL, sondern auch für die Aufruf-URL des Web Services.

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 8 von 17www.oio.de [email protected]

Abbildung 7: Schritt 2: Erstellen des Web Service-Clients

3. Einbinden der für den Aufruf des Web Services vom Web Service Client benötigten Bibliotheken: Rechtsklick auf erstelltes Projekt ->Properties -> auf linker Seite Libraries auswählen -> auf rechter Seite auf „Add JAR/Folder„ klicken um die Bibiliotheken webservices-rt.jarund webservices-tools.jar aus METRO_HOME/lib auszuwählen -> OK. (METRO_HOME entspricht dem Pfad zum Metro-Ordner der bei derInstallation von Metro erzeugt wurde).

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 9 von 17www.oio.de [email protected]

Abbildung 8: Schritt 3: Einbinden der benötigten Bibliotheken

4. Anschließend müssen die Stub-Klassen zum Aufruf des Web Services generiert werden: Im Projekt den Ordner "Web Service References"expandieren -> Rechtsklick auf UsernameTokenServiceService -> Edit Web Service Attributes -> Haken bei Use development defaults(HINWEIS: Der Haken erscheint nicht, Bug in NetBeans, erfolgreich wenn nach Klick auf Finish im Ordner „Source Packages„ der OrdnerMETA-INF erstellt wurde).

5. Unter „Source Packages“ die Datei META-INF\UsernameTokenServiceService.xml editieren. Der Benutzername und das Passwort sollenzur Laufzeit bestimmt werden, daher muss die statische Konfiguration entfernt werden (siehe Screenshot).

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 10 von 17www.oio.de [email protected]

Abbildung 9: Schritt 5: Entfernen des sc:CallbackHandlerConfiguration-Elements (markierter Bereich).

6. In UsernameTokenServiceService.xml muss jetzt die Konfiguration für den zu verwendenden Public Key des Servers angepasst werden.Dieser befindet sich in einem JKS-Keystore namens „client-truststore.jks„und wird über das location-Attribut ausgewählt, welches demTrustStore-Element hinzuzufügen ist: <sc:TrustStore location="client-truststore.jks" …/> Die Änderungen anUsernameTokenServiceService.xml werden jetzt gespeichert: File -> Save all.

Der Public Key des Servers wird benötigt, um den zur Laufzeit erzeugten symmetrischen Schlüssel zur Verschlüsselung des UsernameTokensfür den Server zu verschlüsseln. Der Server entschlüsselt dann mit seinem Private Key den symmetrischen Schlüssel und verwendet diesenzur Entschlüsselung des UsernameTokens. Anhand der Informationen im UsernameToken führt er dann die Zugriffskontrolle aus.

Verschlüsselungsoperationen mit WS-Security

Wenn man sich die Vorgehensweise bei der Verschlüsselung betrachtet, fällt einem auf, dass das UsernameToken auch direkt mit demPublic Key des Servers verschlüsselt werden könnte. WS-Security verbietet jedoch den Einsatz von Public Key-Verschlüsselung fürandere Elemente. Nur symmetrische Schlüssel dürfen mittels Public Key-Kryptographie verschlüsselt werden. Diese Entscheidung beruhtauf der Tatsache, dass die Laufzeit von Public Key-Algorithmen um ein Vielfaches schlechter ist als die von symmetrischen Algorithmen.Daher sollten diese nur zur Verschlüsselung von kleinen Datenmengen, wie eben einem Schlüssel, verwendet werden.

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 11 von 17www.oio.de [email protected]

Abbildung 10: Schritt 6: Setzen des location-Attributs zur Auswahl des TrustStores.

7. Minimieren Sie NetBeans und wechseln Sie mit dem Windows-Explorer oder ähnlichem in das Hauptverzeichnis des Client-Projektes aufIhrer Festplatte. Kopieren Sie den src\META-INF-Ordner in den build\classes-Ordner. Kopieren Sie die DateiGLASSFISH_HOME\domains\domain1\config\cacerts.jks nach build\classes\META-INF und nennen Sie sie in „client-truststore.jks„ um.GLASSFISH_HOME bezeichnet das Wurzelverzeichnis ihrer GlassFish-Installation.

Nun muss der eigentliche Anwendungscode zum Aufruf des gesicherten Services geschrieben werden. Der Ablauf sieht wie folgt aus: inclient.Main wird der Benutzername und das Passwort von der Kommandokonsole gelesen. Diese Daten werden dann in der Klassesecurity.UserPasswordInfo in dafür vorgesehenen statischen Variablen hinterlegt und sind somit für den JAX-WS-Handlersecurity.UsernameTokenHandler abrufbar. Dieser Handler erzeugt dann aufgrund der Benutzerdaten das benötigte UsernameToken.

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 12 von 17www.oio.de [email protected]

Abbildung 11: Schritt 7: Die wesentlichen Schritte der Client-Implementierung als Sequence Diagram.

8. security.UserPasswordInfo implementieren:

package security;public class UserPasswordInfo{private static String username;private static String password;public static String getPassword(){return password;

}public static void setPassword(String password){UserPasswordInfo.password = password;

}public static String getUsername(){return username;

}public static void setUsername(String username){UserPasswordInfo.username = username;

}}

Beispiel 3: security.UserPasswordInfo

9. security.UsernameTokenHandler implementieren:

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 13 von 17www.oio.de [email protected]

package security;import java.util.Set;import javax.xml.namespace.QName;import javax.xml.ws.handler.MessageContext;import javax.xml.ws.handler.soap.*;import java.util.*;public class UsernameTokenHandlerimplements SOAPHandler<SOAPMessageContext>{public Set<QName> getHeaders(){return null;

}public boolean handleMessage(SOAPMessageContext context){Boolean isOutbound =(Boolean)context.get(context.MESSAGE_OUTBOUND_PROPERTY);if(isOutbound.booleanValue()){context.put(com.sun.xml.wss.XWSSConstants.USERNAME_PROPERTY,UserPasswordInfo.getUsername());context.put(com.sun.xml.wss.XWSSConstants.PASSWORD_PROPERTY,UserPasswordInfo.getPassword());

}return true;

}public boolean handleFault(SOAPMessageContext context){return true;

}public void close(MessageContext context){}

}

Beispiel 4: security.UsernameTokenHandler:

Relevant ist nur die Implementierung der handleMessage-Methode. In ihr wird zunächst überprüft, ob der Handler für eine ausgehendeNachricht (also eine Nachricht hin zum Server) aufgerufen wird. Ist dies der Fall, werden die Benutzername- und Passwort-Werte desUsernameTokens gesetzt.

10. Jetzt muss noch client.Main implementiert werden (Siehe Beispiel 5):

Zu Beginn werden die für den Service-Aufruf zu verwendenden Benutzerdaten von der Kommandokonsole gelesen und in UserPasswordInfohinterlegt. Dann werden die generierten Service Client-Klassen verwendet und der UsernameTokenHandler als Handler für Service-Aufrufehinzugefügt. Es folgt der eigentliche Service-Aufruf. Das Setzen der System-Property bewirkt die Ausgabe der ausgetauschtenSOAP-Nachrichten auf der Konsole. Für eine übersichtlichere Form eignet sich das Tool TCPMon [9].

11. Abschließend kann der Client gestartet werden: File -> Save All. Dann Rechtsklick auf Client-Projekt -> Build. Dann Rechtsklick aufclient.Main und Run File wählen. Geben Sie den Benutzernamen und das Passwort des von Ihnen erstellten Benutzers ein.

In diesem Artikel wurden die benötigten Schritte aufgezeigt, um einen Web Service mittels NetBeans und GlassFish perPasswort-Authentifizierung zu schützen und einen dazugehörigen Client zu erstellen. Zunächst wurde der zu sichernde Web Service erstelltund mit dem Sicherheitsmechanismus Username Authentication with Symmetric Key geschützt, um die Authentifizierung per UsernameTokenzu aktivieren. Dann wurde ein Benutzer zur Nutzung des Services unter Angabe von Benutzername und Passwort in GlassFish eingerichtet.Die Erstellung des zugehörigen Standalone-Clients benötigte im Vergleich zu den ersten beiden Schritten mehr Handarbeit. Nach demErstellen der Stub-Klassen war die erstellte Konfigurationsdatei anzupassen sowie zusammen mit dem benötigten Keystore-File an dierichtige Stelle zu kopieren. Kern der Client-Anwendungslogik war das Setzen des abgefragten Benutzernamens und Passworts in einemJAX-WS-Handler.

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 14 von 17www.oio.de [email protected]

package client;import javax.xml.ws.*;import javax.xml.ws.handler.*;import java.util.*;import java.io.*;import security.*;public class Main{public static void main(String[] args){try{System.out.println("Bitte geben Sie ihren Benutzernamen ein: ");BufferedReader reader =

new BufferedReader(new InputStreamReader(System.in));UserPasswordInfo.setUsername(reader.readLine());System.out.println("Bitte geben Sie ihr Passwort ein: ");UserPasswordInfo.setPassword(reader.readLine());reader.close();System.setProperty("com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump", "true");server.UsernameTokenServiceService service =

new server.UsernameTokenServiceService();server.UsernameTokenService port =

service.getUsernameTokenServicePort();BindingProvider prov = (BindingProvider)port;List<Handler> handlerChain =

prov.getBinding().getHandlerChain();handlerChain.add(new UsernameTokenHandler());prov.getBinding().setHandlerChain(handlerChain);prov.getRequestContext().put(prov.ENDPOINT_ADDRESS_PROPERTY,

"http://localhost:8080/UsernameTokenService/UsernameTokenServiceService");

java.lang.String name = "Test";java.lang.String result = port.sayHello(name);System.out.println("Result = "+result);

}catch (Exception ex){ex.printStackTrace();

}}

}

Beispiel 5: client.Main:

Die fertigen Projekte stehen unter [10] zum Download bereit. Dabei ist zu beachten, dass das Keystore-File des Client-Projektes wie im Artikelbeschrieben zu ersetzen ist. Außerdem müssen im Client-Projekt die Pfade zu den benötigten Libraries an die lokale Installation angepasstwerden.

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 15 von 17www.oio.de [email protected]

Abbildung 12: Überblick auf die Lösung

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 16 von 17www.oio.de [email protected]

REFERENZEN

• [1] Web Service Security (WSS)(http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0.pdf)

• [2] UsernameTokenProfile(http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf)

• [3] Metro(https://metro.dev.java.net/)

• [4] GlassFish V2 UR2(https://glassfish.dev.java.net/downloads/v2ur2-b04.html)

• [5] Metro 1.2(https://metro.dev.java.net/1.2/)

• [6] Metro 1.2 Install(https://metro.dev.java.net/nonav/1.2/docs/install.html)

• [7] GlassFish-Zertifikatupdate(http://docs.sun.com/app/docs/doc/820-1072/6ncp48v4k?a=view)

• [8] NetBeans 6.5(http://www.netbeans.org/downloads/index.html)

• [9] TCPMon(http://ws.apache.org/commons/tcpmon/)

• [10] Download: Fertige Projekte(/public/xml/token/usernametoken-tutorial-beispiele.zip)

Web Services mit UsernameToken sichern© Trivadis Germany GmbHSeite 17 von 17www.oio.de [email protected]