Sie können von einem externen Sicherheitstokenservice
(STS) ein Authentifizierungstoken anfordern und dieses dann über das Programmiermodell
Java™ API
for XML-Based Web Services (JAX-WS) und WSS-APIs (Web Services
Security APIs) mit Schutz auf Nachrichten- oder Transportebene senden.
Vorbereitende Schritte
Für diese Task müssen Sie mit dem Programmiermodell JAX-WS, den WSS-APIs, mit WebSphere-WSS-Anmeldemodulen für generische Sicherheitstoken, mit SAML-Konzepten, mit SSL-Transportschutz, mit Schutz auf
Nachrichtenebene sowie mit Richtliniensätzen zum Konfigurieren und Verwalten von Web-Service-Einstellungen vertraut sein.
Informationen zu diesem Vorgang
Die für diese Task verwendete Web-Service-Clientanwendung ist eine modifizierte Version des
Clientcodes, der in der zum Download verfügbaren Beispielanwendung JaxWSServicesSamples enthalten ist. In der Prozedur sind Codeauszüge des Beispiels beschrieben. Außerdem wird ein
vollständiger, sofort einsatzfähiger Beispiel-Web-Service-Client bereitgestellt.
Gehen Sie wie folgt vor, um bei einem externen STS ein
SAML-Bearer-Authentifizierungstoken anzufordern und dieses dann zu senden:
Vorgehensweise
- Ermitteln Sie den Web-Service-Client, mit dem Sie einen Web-Service-Provider aufrufen möchten, und fordern Sie diesen Client an. Fordern Sie mit diesem Client Authentifizierungstoken an und fügen Sie sie über WSS-APIs
programmgestützt in die SOAP-Anforderungsnachrichten ein. Der in dieser Prozedur verwendete Web-Service-Client ist eine modifizierte Version des
Clientcodes, der in der zum Download verfügbaren Web-Service-Beispielanwendung JaxWSServicesSamples enthalten ist.
Führen Sie die folgenden Schritte aus, um den Beispiel-Web-Service-Client anzufordern und mit WSS-APIs zu modifizieren, um
ein Sicherheitstoken programmgestützt in der SOAP-Anforderungsnachricht übergeben zu können:
- Laden Sie die Beispielanwendung JaxWSServicesSamples herunter. Das Beispiel JaxWSServicesSamples ist standardmäßig nicht installiert.
- Fordern Sie den Clientcode für JaxWSServicesSamples an. Die Prozedur nutzt in diesem Beispiel eine modifizierte Version des
Thin-Client-Beispiels Echo, das
Teil des Beispiels JaxWSServicesSamples ist.
Die Beispieldatei SampleClient.java des Web-Service-Thin-Client "Echo"
befindet sich im Verzeichnis src\SampleClientSei\src\com\ibm\was\wssample\sei\cli.
Die Beispielklassendatei ist in der Datei WSSampleClientSei.jar enthalten.
Die Unternehmensanwendung
JaxWSServicesSamples.ear und die unterstützenden JAR-Dateien (Java-Archiv)
befinden sich im Verzeichnis installableApps in der Beispielanwendung
"JaxWSServicesSamples".
- Implementieren Sie die Datei JaxWSServicesSamples.ear auf dem Anwendungsserver. Nach der Implementierung der Datei JaxWSServicesSamples.ear können Sie den Code des Beispiel-Web-Service-Clientcodes
anhand der Beispielanwendung testen.
Anstatt den Richtliniensatz für den Schutz des Beispiel-Web-Service-Client zu verwenden, können Sie auch die
Codefragmente hinzufügen, um in Ihrer eigenen Web-Service-Clientanwendung
Authentifizierungstoken über WSS-APIs programmgestützt in der SOAP-Anforderungsnachricht zu übergeben. Das Beispiel in dieser Prozedur nutzt einen Web Service Thin Client für JAX-WS.
Sie können aber auch einen verwalteten Client verwenden.
- Ordnen Sie den Standardrichtliniensatz
SAML11 Bearer WSHTTPS dem Web-Service-Provider zu. Dieser Richtliniensatz wird verwendet, um Nachrichten mittels HTTPS-Transport zu schützen. Lesen Sie hier, wie die Client- und Providerbindungen für das
SAML-Bearer-Token konfiguriert werden, und erfahren Sie, wie der Standardrichtliniensatz SAML11 Bearer WSHTTPS Ihrem Web-Service-Provider zugeordnet
wird.
- Weisen Sie die allgemeinen Standardbindungen von "SAML Bearer Provider sample" dem Beispiel-Web-Service-Provider zu. Lesen Sie hier, wie die Client- und Providerbindungen für
das SAML-Bearer-Token konfiguriert werden, und erfahren Sie, wie die allgemeinen Standardbindungen des SAML-Bearer-Providerbeispiels Ihrer Web-Service-Anwendung zugeordnet
werden.
- Prüfen Sie, ob die angepassten Eigenschaften trustStoreType, trustStorePassword
und trustStorePath dem Truststore mit dem STS-Unterzeichnerzertifikat entsprechen. Führen Sie in der Administrationskonsole die folgenden Schritte aus:
- Klicken Sie auf .
- Klicken Sie in der Tabelle der Authentifizierungstoken auf
con_saml11token.
- Klicken Sie auf Callback-Handler.
- Vergewissern Sie sich im Abschnitt "Angepasste Eigenschaften", dass die angepassten Eigenschaften trustStoreType, trustStorePassword
und trustStorePath dem Truststore mit dem STS-Unterzeichnerzertifikat entsprechen.
- Wenn Sie die Web-Service-Anforderung oder WS-Trust-Anforderung mit SSL auf Transportebene schützen,
legen Sie die SSL-Konfiguration mit der folgenden JVM-Eigenschaft fest.
-Dcom.ibm.SSL.ConfigURL=file:<Profilstammverzeichnis>\properties\ssl.client.props
Alternativ können Sie mit einer
Java-Systemeigenschaft im Beispielclientcode die SSL-Konfigurationsdatei wie folgt definieren:
System.setProperty("com.ibm.SSL.ConfigURL", "file:Profilstammverzeichnis/properties/ssl.client.props");
- Fügen Sie die JAR-Datei für den JAX-WS Thin Client zum Klassenpfad hinzu:
Stammverzeichnis_des_Anwendungsservers/runtimes/com.ibm.jaxws.thinclient_8.5.0.jar. Lesen Sie die Informationen zum Testen von Clients mit Unterstützung für Web Services, um zu erfahren, wie diese JAR-Datei
zum Klassenpfad hinzugefügt wird.
- Fordern Sie das Authentifizierungstoken von einem externen STS an. Das folgende Codefragment veranschaulicht die Anforderung des
Authentifizierungstokens, das mit dem WebSphere-Anmeldemodul für generische Sicherheitstoken verwendet werden soll. Hierbei wird vorausgesetzt, dass ein externer STS so konfiguriert ist, dass er
ein Benutzernamenstoken als Authentifizierungstoken akzeptiert und ein
SAML-1.1-Token ausstellt.
// Sicherheitstoken vom externen STS anfordern
WSSFactory factory = WSSFactory.getInstance();
// STS-URL für Ausstellung des angeforderten Tokens
String STS_URI = "https://externalstsserverurl:port/TrustServerWST13/services/RequestSecurityToken";
// Web-Service-Endpunkt für Empfang des ausgestellten Tokens
String ENDPOINT_URL = "http://localhost:9080/WSSampleSei/EchoService";
// Beispielcode 1 - Anfang (Token mit WS-Trust Issue beim STS anfordern.
// Authentifizierungstoken wird über WS-Security-Header gesendet.)
HashMap<Object, Object> cbackMap1 = new HashMap<Object, Object>();
cbackMap1.put(IssuedTokenConfigConstants.STS_ADDRESS, STS_URI);
cbackMap1.put(IssuedTokenConfigConstants.APPLIES_TO, ENDPOINT_URL);
// Die folgende Eigenschaft gibt an, dass die WS-Trust-Anforderung mit
// der Spezifikation WS-Trust 1.3 konform sein muss.
cbackMap1.put(IssuedTokenConfigConstants.TRUST_CLIENT_WSTRUST_NAMESPACE,
"http://docs.oasis-open.org/ws-sx/ws-trust/200512");
cbackMap1.put(IssuedTokenConfigConstants.TRUST_CLIENT_COLLECTION_REQUEST, "false");
// Diese Anforderung erfolgt ausschließlich mit WS-TRust Issue (und ohne
// WS-Trust Validate)
cbackMap1.put(IssuedTokenConfigConstants.USE_RUN_AS_SUBJECT, "false");
GenericIssuedTokenGenerateCallbackHandler cbHandler1 =
new GenericIssuedTokenGenerateCallbackHandler (cbackMap1);
// Kontextobjekt für WS-Trust-Anforderung erstellen
WSSGenerationContext gencont1 = factory.newWSSGenerationContext();
WSSConsumingContext concont1 = factory.newWSSConsumingContext();
// UNT für Authentifizierung der Trust-Anforderung verwenden
UNTGenerateCallbackHandler utCallbackHandler = new UNTGenerateCallbackHandler("testuser", "testuserpwd");
SecurityToken ut = factory.newSecurityToken(UsernameToken.class, utCallbackHandler);
gencont1.add(ut);
cbHandler1.setWSSConsumingContextForTrustClient(concont1);
cbHandler1.setWSSGenerationContextForTrustClient(gencont1);
// Beispielcode 1 - Ende
// Beispielcode 2 - Anfang (Token mit WS-Trust Validate anfordern und
// dabei ein Token im RunAs-Subjekt austauschen)
// Falls der Web-Service-Client ein RunAs-Subjekt hat, weil beispielsweise ein
// authentifizierter zwischengeschalteter Server als Client den nachgeordneten
// Service aufrut, können Sie den Client so konfigurieren, dass er das Token vom
// RunAs-Subjekt über WS-Trust Validate mit dem STS austauscht.
// Ersetzen Sie dazu den Beispielcode 1 durch folgenden Code:
HashMap<Object, Object> cbackMap1 = new HashMap<Object, Object>();
cbackMap1.put(IssuedTokenConfigConstants.STS_ADDRESS, STS_URI);
cbackMap1.put(IssuedTokenConfigConstants.APPLIES_TO, ENDPOINT_URL);
// Diese Anforderung erfolgt mit WS-Trust 1.3
cbackMap1.put(IssuedTokenConfigConstants.TRUST_CLIENT_WSTRUST_NAMESPACE,
"http://docs.oasis-open.org/ws-sx/ws-trust/200512");
cbackMap1.put(IssuedTokenConfigConstants.TRUST_CLIENT_COLLECTION_REQUEST, "false");
// Fügen Sie die folgende Zeile hinzu, wenn beim Scheitern des Tokenaustauschs
// nicht auf WS-Trust Issue zurückgegriffen werden soll.
cbackMap1.put(IssuedTokenConfigConstants.USE_RUN_AS_SUBJECT_ONLY, "true");
// Fügen Sie die folgende Zeile hinzu, um in dem für den Austausch des
// angeforderten Tokens verwendeten RunAs-Subjekt den Tokentyp anzugeben.
// Verwenden Sie zum Anfordern eines SAML-Tokens beispielsweise ein
// LTPA-Token für den Austausch. Wenn das austauschte Token im RunAs-Subjekt
// denselben Wertetyp wie das angeforderte Token hat, ist die Einstellung
// IssuedTokenConfigConstants.USE_TOKEN nicht erforderlich.
cbackMap1.put(IssuedTokenConfigConstants.USE_TOKEN, LTPAToken.ValueType);
GenericIssuedTokenGenerateCallbackHandler cbHandler1 =
new GenericIssuedTokenGenerateCallbackHandler (cbackMap1);
// Der folgende Code wird hinzugefügt, wenn ein Authentifizierungstoken im
// WS-Security-Header oder der Schutz auf Nachrichtenebene erforderlich
// ist. Falls es keinen Schutz auf Nachrichtenebene und kein zusätzliches
// Authentifizierungstoken für WS-Trust Validate gibt, müssen Sie das
// folgende Kontextobjekt nicht erstellen.
// Kontextobjekt für WS-Trust-Anforderung:
WSSGenerationContext gencont1 = factory.newWSSGenerationContext();
WSSConsumingContext concont1 = factory.newWSSConsumingContext();
// UNT für Authentifizierung der Trust-Anforderung verwenden
UNTGenerateCallbackHandler utCallbackHandler =
new UNTGenerateCallbackHandler("testuser", "testuserpwd");
SecurityToken ut = factory.newSecurityToken(UsernameToken.class, utCallbackHandler);
gencont1.add(ut);
cbHandler1.setWSSConsumingContextForTrustClient(concont1);
cbHandler1.setWSSGenerationContextForTrustClient(gencont1);
// Beispielcode 2 - Ende
GenericSecurityToken token = (GenericSecurityToken) factory.newSecurityToken
(GenericSecurityToken.class, cbHandler1, "system.wss.generate.issuedToken");
// Der folgende Schritt zum Festlegen des Wertetyps ist erforderlich.
// Der Parameter ist immer der QName für den valueType (Wertetyp) des
// angeforderten Tokens.
// QName für SAML1.1:
QName Saml11ValueType = new QName(WSSConstants.SAML.SAML11_VALUE_TYPE);
token.setValueType(Saml11ValueType);
// Enthält QName-Definitionen für SAML11, SAML20,
// TAM-Token und PassTicket-Token.
// QName für SAML 2.0:
QName Saml20ValueType = new QName(WSSConstants.SAML.SAML20_VALUE_TYPE);
token.setValueType(Saml11ValueType);
// QName für TAM-Token:
QName TamValueType = new QName("http://ibm.com/2004/01/itfim/ivcred");
// QName für PassTicket-Token:
QName PassTicketValueType = new QName("http://docs.oasis-open.org/wss/
2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken");
// Über die Tokenschnittstelle können Sie den ValueType QName für
// alle anderen Token abrufen. Der QName für ein Benutzernamenstoken
// lautet beispielsweise UsernameToken.ValueType.
Das Objekt GenericIssuedTokenGenerateCallbackHandler enthält Parameter, die die Merkmale des anzufordernden
Sicherheitstokens definieren, und weitere Parameter, die erforderlich sind, um den STS zu erreichen und das Sicherheitstoken anzufordern. Das Objekt
GenericIssuedTokenGenerateCallbackHandler gibt
die in der folgenden Tabelle beschriebenen Konfigurationsparameter an.
Tabelle 1. Eigenschaften für GenericIssuedTokenGenerateCallbackHandler. In der folgenden Tabelle sind die Konfigurationsparameter für das Objekt
GenericIssuedTokenGenerateCallbackHandler beschrieben.Eigenschaft |
Beschreibung |
Erforderlich |
IssuedTokenConfigConstants.STS_ADDRESS |
Gibt die HTTP-Adresse des STS an Wenn die Kommunikation mit dem STS mithilfe von
SSL geschützt wird, müssen Sie die Eigenschaft -Dcom.ibm.SSL.ConfigURL setzen.
Eine SSL-Verbindung zum STS wird durch das Adresspräfix https:// angezeigt.
|
Ja |
IssuedTokenConfigConstants.APPLIES_TO |
Gibt die Adresse des Zielservice an, an der Sie das Token
verwenden möchten |
Nein |
IssuedTokenConfigConstants.TRUST_CLIENT_COLLECTION_REQUEST |
Gibt an, ob beim STS ein einzelnes, in einem Element
RequestSecurityToken
(RST) eingeschlossenes Token angefordert werden soll oder eine Gruppe von RST-Elementen, die in nur einem
Element RequestSecurityTokenCollection (RSTC) eingeschlossen sind. Standardmäßig wird ein Einzeltoken angefordert, das in
einem Element
RequestSecurityToken (RST) vom STS eingeschlossen ist.
Wenn Sie für diese Eigenschaft den
Wert true angeben, werden mehrere Token in einer Gruppe von
RST-Elementen angefordert, die in einem einzelnen Element RequestSecurityTokenCollection (RSTC)
vom STS eingschlossen ist.
Der Standardwert ist
false.
|
Nein |
IssuedTokenConfigConstants.TRUST_CLIENT_WSTRUST_NAMESPACE |
Gibt den in der WS-Trust-Anforderung enthaltenen WS-Trust-Namespace
an Der Standardwert ist WSTrust 1.3.
|
Nein |
IssuedTokenConfigConstants.USE_RUN_AS_SUBJECT |
Gibt an, ob WS-Security zunächst WS-Trust Validate verwenden soll, um
das Token aus dem RunAs-Subjekt gegen das angeforderte Token auszutauschen. Der Wert false gibt an,
dass WS-Security das Token mit
WS-Trust Issue anfordern soll. Der Standardwert ist true.
|
Nein |
IssuedTokenConfigConstants.USE_RUN_AS_SUBJECT_ONLY |
Gibt an, dass WS-Security beim Scheitern des Tokenaustauschs nicht
WS-Trust Issue verwenden soll, um das Token anzufordern. Der Standardwert ist
false.
|
Nein |
IssuedTokenConfigConstants.USE_TOKEN |
Dieser Wert wird verwendet, um ein Token für das RunAs-Subjekt auszuwählen,
für das das angeforderte Token eingetauscht werden soll. Der Standardwert ist der
ValueType des angeforderten Tokens.
|
Nein |
Außerdem werden im Objekt GenericIssuedTokenGenerateCallbackHandler eine Instanz von WSSGenerationContext
und von WSSConsumingContext
definiert. In diesem Beispiel enthält die Instanz von WSSGenerationContext
ein Objekt UNTGenerateCallbackHandler mit Informationen zur Erstellung
des UsernameToken, das an den STS gesendet werden soll.
Der Parameter
system.wss.generate.issuedToken gibt
das für die Erstellung des generischen Sicherheitstokens zu verwendende JAAS-Anmeldemodul (Java Authentication and Authorization Service)
an. Sie müssen eine
JVM-Eigenschaft angeben, um eine JAAS-Konfigurationsdatei mit der erforderlichen
JAAS-Anmeldekonfiguration zu definieren. Beispiel:
-Djava.security.auth.login.config=Profilstammverzeichnis/properties/wsjaas_client.conf
Alternativ können Sie eine
Java-Systemeigenschaft im Beispielclientcode setzen, um eine JAAS-Anmeldekonfigurationsdatei anzugeben,
z. B.
System.setProperty("java.security.auth.login.config", "Profilstammverzeichnis/properties/wsjaas_client.conf");
- Fügen Sie das beim STS angeforderte Authentifizierungstoken zum SOAP-Sicherheitsheader von Web-Service-Anforderungsnachrichten hinzu.
- Initialisieren Sie den Web-Service-Client und konfigurieren Sie die Eigenschaften von
SOAPAction. Diese Aktionen veranschaulicht der folgende Code:
// Web-Service-Client initialisieren
EchoService12PortProxy echo = new EchoService12PortProxy();
echo._getDescriptor().setEndpoint(endpointURL);
// SOAPAction-Eigenschaften konfigurieren
BindingProvider bp = (BindingProvider) (echo._getDescriptor().getProxy());
Map<String, Object> requestContext = bp.getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
requestContext.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
requestContext.put(BindingProvider.SOAPACTION_URI_PROPERTY, "echoOperation");
// WSSGenerationContext initialisieren
WSSGenerationContext gencont = factory.newWSSGenerationContext();
gencont.add(token);
- Initialisieren Sie das Objekt WSSGenerationContext. Der folgende Code veranschaulicht die Verwendung der Methode WSSFactory.newWSSGenerationContext zum Anfordern eines
Objekts WSSGenerationContext. Mit dem Objekt WSSGenerationContext wird dann
das Token in eine Web-Service-Anforderungsnachricht eingefügt.
// WSSGenerationContext initialisieren
WSSGenerationContext gencont = factory.newWSSGenerationContext();
gencont.add(token);
Die Methode WSSGenerationContext.add erfordert, dass
der Clientcode über die folgende Java-2-Sicherheitsberechtigung verfügt: permission javax.security.auth.AuthPermission "modifyPrivateCredentials"
- Fügen Sie für den Nachrichtenschutz ein X.509-Token hinzu. (Übergehen Sie diesen Schritt,
wenn der Web Service nur mit SSL auf Transportebene geschützt wird.) Im folgenden Beispielcode werden die Schlüsseldatei
dsig-sender.ks und der Beispielschlüssel SOAPRequester verwendet. In einer Produktionsumgebung dürfen Sie den Beispielschlüssel nicht verwenden. Der folgende
Code veranschaulicht das Hinzufügen eines X.509-Tokens für den Nachrichtenschutz.
// X.509-Token für Nachrichtenschutz hinzufügen
X509GenerateCallbackHandler x509callbackHandler = new X509GenerateCallbackHandler(
null,
"profile_root/etc/ws-security/samples/dsig-sender.ks",
"JKS",
"client".toCharArray(),
"soaprequester",
"client".toCharArray(),
"CN=SOAPRequester, OU=TRL, O=IBM, ST=Kanagawa, C=JP", null);
SecurityToken x509 = factory.newSecurityToken(X509Token.class,
x509callbackHandler, "system.wss.generate.x509");
WSSSignature sig = factory.newWSSSignature(x509);
sig.setSignatureMethod(WSSSignature.RSA_SHA1);
WSSSignPart sigPart = factory.newWSSSignPart();
sigPart.setSignPart(token);
sigPart.addTransform(WSSSignPart.TRANSFORM_STRT10);
sig.addSignPart(sigPart);
sig.addSignPart(WSSSignature.BODY);
- Erstellen Sie ein Objekt WSSSignature mit dem X.509-Token. Die folgende Codezeile erstellt ein Objekt WSSSignature mit dem
X.509-Token:
WSSSignature sig = factory.newWSSSignature(x509);
- Fügen Sie den signierten Abschnitt für den Nachrichtenschutz hinzu. Die folgende Codezeile gibt an, dass WSSSignature.BODY
als signierter Abschnitt hinzugefügt werden soll:
sig.addSignPart(WSSSignature.BODY);
- Fügen Sie zum SOAP-Sicherheitsheader das Element Timestamp hinzu. Die Richtliniensätze SAML20 SenderVouches WSHTTPS und
SAML11 SenderVouches
WSHTTPS erfordern, dass Web-Service-Anforderungen und -Antworten im SOAP-Sicherheitsheader ein Element
Timestamp enthalten.
Im folgenden Code generiert der Methodenaufruf WSSFactory.newWSSTimestamp() ein Element
Timestamp und der Methodenaufruf WSSGenerationContext.add(timestamp) fügt das Element Timestamp
in die Anforderungsnachricht ein:
// Element "Timestamp" hinzufügen
WSSTimestamp timestamp = factory.newWSSTimestamp();
gencont.add(timestamp);
sig.addSignPart(WSSSignature.TIMESTAMP);
gencont.add(sig);
WSSConsumingContext concont = factory.newWSSConsumingContext();
- Übergehen Sie den folgenden Schritt, wenn keine Tokensignatur erforderlich ist. Falls das angeforderte Sicherheitstoken
über die Verweisoption STR
Dereference Transform signiert werden muss, führen Sie Schritt 1 aus. Fahren Sie andernfalls mit Schritt 2 fort.
Die Verweisoption STR Dereference Transform wird allgemein als
STR-Transform bezeichnet.
Schritt 1:
Einige Token können nicht direkt digital signiert werden. Zu diesen gehören unter anderem SAML-Token. In dem Fall müssen Sie das Token mittels STR-Transform signieren.
Zum Signieren über STR-Transform muss ein Element
<wsse:SecurityTokenReference> im Headerblock
<wsse:Security> auf das zu signierende Token verweisen. Wenn ein Sicherheitstoken mittels STR-Transform signiert werden soll, wird zum Angeben der
SecurityTokenReference mit einem Umsetzungsalgorithmus,
ein separater Abschnitt WSSSignPart erstellt, der
vom Attribut WSSSignPart.TRANSFORM_STRT10 repräsentiert wird. Mithilfe dieses Attributs
kann die WS-Security-Laufzeitumgebung ein Element
SecurityTokenReference generieren, das auf das Token verweist und das Token mit der
Verweisoption STR Deference digital signiert.
Der folgende
Code veranschaulicht die Verwendung des Attributs WSSSignPart.TRANSFORM_STRT10:
WSSSignPart sigPart = factory.newWSSSignPart();
sigPart.setSignPart(token);
sigPart.addTransform(WSSSignPart.TRANSFORM_STRT10);
Schritt 2:
Wenn das angeforderte signierte Token kein SAML-Token ist oder STR-Transform nicht angewendet wird,
verwenden Sie stattdessen den folgenden Code:
sig.addSignPart(token);
- Fügen Sie das Objekt WSSGenerationContext zum Web-Service-Objekt
RequestContext hinzu. Das Objekt WSSGenerationContext enthält jetzt alle Sicherheitsinformationen, die für das Formatieren einer
Anforderungsnachricht erforderlich sind. Die Methode WSSGenerationContext.process(requestContext) ordnet
das Objekt WSSGenerationContext dem Web-Service-Objekt
RequestContext zu, damit die WS-Security-Laufzeitumgebung
den erforderlichen SOAP-Sicherheitsheader formatieren kann. Beispiel:
// Objekt WSSGenerationContext zum Web-Service-Objekt RequestContext hinzufügen
gencont.process(requestContext);
- Wenn die Providerrichtlinie eine digital signierte Antwortnachricht erfordert, validieren Sie die digitale Signatur und
die Integrität der Antwortnachricht mit dem X.509-Token. Übergehen Sie den folgenden Schritt, wenn Sie den Schutz auf Transportebene mit SSL verwenden.
- Ein Objekt X509ConsumeCallbackHandler wird mit einem Truststore
und einer Liste von Zertifikatspfadobjekten initialisiert, um die digitale Signatur in einer Antwortnachricht
zu validieren. Der folgende Code initialisiert das Objekt X509ConsumeCallbackHandler mit dem Truststore
dsig-receiver.ks und einem Zertifikatspfadobjekt
certList:
ArrayList certList = new ArrayList();
java.security.cert.CertStore certStore = java.security.cert.CertStore.getDefaultType();
certList.add(certStore);
X509ConsumeCallbackHandler callbackHandlerVer = new
X509ConsumeCallbackHandler("profile_root/etc/ws-security/samples/dsig-receiver.ks",
"JKS",
"server".toCharArray(),
certList,
java.security.Security.getProvider("IBMCertPath"));
- Ein Verifizierungsobjekt WSSVerification wird erstellt, zu dem der Nachrichtenhauptteil hinzugefügt wird, damit
die WS-Security-Laufzeitumgebung die digitale Signatur validiert. Das Objekt WSSVerification wird mit folgendem Code initialisiert:
WSSVerification ver = factory.newWSSVerification(X509Token.class, callbackHandlerVer);
Das Objekt
WSSConsumingContext enthält jetzt alle Sicherheitsinformationen, die für das Formatieren einer
Anforderungsnachricht erforderlich sind. Die Methode WSSConsumingContext.process(requestContext) ordnet das Objekt
WSSConsumingContext der Antwortmethode zu.
Beispiel: // Objekt WSSConsumingContext zum Web-Service-Objekt RequestContext hinzufügen
concont.process(requestContext);
Ergebnisse
Sie haben ein Sicherheitstoken von einem externen STS angefordert.
Das angeforderte Token haben Sie
dann mit Web-Service-Anforderungsnachrichten mit Nachrichtenschutz über das
JAX-WS-Programmiermodell und WSS-APIs gesendet.
Beispiel
Das folgende Codebeispiel ist eine
Web-Service-Clientanwendung, die veranschaulicht, wie ein
SAML-Bearer-Token von einem externen STS angefordert und in einer Web-Service-Anforderungsnachricht gesendet
wird. Falls Ihr Einsatzszenario SAML-Token erfordert, jedoch nicht die Übergabe der SAML-Token mit Web-Service-Nachrichten durch Ihrer Anwendung,
müssen Sie nur den ersten Abschnitt des folgenden Beispielcodes
bis einschließlich des Abschnitts
// Web-Service-Client
initialisieren verwenden.
package com.ibm.was.wssample.sei.cli;
import com.ibm.was.wssample.sei.echo.EchoService12PortProxy;
import com.ibm.was.wssample.sei.echo.EchoStringInput;
import com.ibm.websphere.wssecurity.wssapi.WSSConsumingContext;
import com.ibm.websphere.wssecurity.wssapi.WSSFactory;
import com.ibm.websphere.wssecurity.wssapi.WSSGenerationContext;
import com.ibm.websphere.wssecurity.wssapi.WSSTimestamp;
import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken;
import com.ibm.websphere.wssecurity.wssapi.token.UsernameToken;
import com.ibm.websphere.wssecurity.callbackhandler.UNTGenerateCallbackHandler;
import com.ibm.wsspi.wssecurity.core.token.config.WSSConstants;
import com.ibm.wsspi.wssecurity.core.config.IssuedTokenConfigConstants;
import com.ibm.websphere.wssecurity.callbackhandler.GenericIssuedTokenGenerateCallbackHandler;
import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityToken;
import javax.xml.namespace.QName;
import java.util.HashMap;
import java.util.Map;
import javax.xml.ws.BindingProvider;
public class SampleSamlSVClient {
private String urlHost = "yourhost";
private String urlPort = "9444";
private static final String CONTEXT_BASE = "/WSSampleSei/";
private static final String ECHO_CONTEXT12 = CONTEXT_BASE+"EchoService12";
private String message = "HELLO";
private String uriString = "https://" + urlHost + ":" + urlPort;
private String endpointURL = uriString + ECHO_CONTEXT12;
private String input = message;
/**
* main()
*
* Befehlszeilenargumente siehe printusage()
*
* @param args
*/
public static void main(String[] args) {
SampleSamlSVClient sample = new SampleSamlSVClient();
sample.CallService();
}
/**
* CallService-Parameter wurden gelesen. Jetzt können die Serviceproxyklassen aufgerufen werden.
*
*/
void CallService() {
String response = "ERROR!:";
try {
System.setProperty("java.security.auth.login.config",
"file:/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/properties/wsjaas_client.conf ");
System.setProperty("com.ibm.SSL.ConfigURL",
"file:/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/properties/ssl.client.props");
// SAML-Token von externem STS anfordern
WSSFactory factory = WSSFactory.getInstance();
String STS_URI = "https://yourhost:9443/TrustServerWST13/services/RequestSecurityToken";
String ENDPOINT_URL = "http://localhost:9081/WSSampleSei/EchoService12";
HashMap<Object, Object> cbackMap1 = new HashMap<Object, Object>();
cbackMap1.put(IssuedTokenConfigConstants.STS_ADDRESS, STS_URI);
cbackMap1.put(IssuedTokenConfigConstants.APPLIES_TO, ENDPOINT_URL);
cbackMap1.put(IssuedTokenConfigConstants.TRUST_CLIENT_WSTRUST_NAMESPACE,
"http://docs.oasis-open.org/ws-sx/ws-trust/200512");
cbackMap1.put(IssuedTokenConfigConstants.TRUST_CLIENT_COLLECTION_REQUEST, "false");
cbackMap1.put(IssuedTokenConfigConstants.USE_RUN_AS_SUBJECT, "false");
GenericIssuedTokenGenerateCallbackHandler cbHandler1 =
new GenericIssuedTokenGenerateCallbackHandler (cbackMap1);
// Kontextobjekt für WS-Trust-Anforderung:
WSSGenerationContext gencont1 = factory.newWSSGenerationContext();
WSSConsumingContext concont1 = factory.newWSSConsumingContext();
// UNT für Authentifizierung der Trust-Anforderung verwenden
UNTGenerateCallbackHandler utCallbackHandler = new
UNTGenerateCallbackHandler("testuser", "testuserpwd");
SecurityToken ut = factory.newSecurityToken(UsernameToken.class, utCallbackHandler);
gencont1.add(ut);
cbHandler1.setWSSConsumingContextForTrustClient(concont1);
cbHandler1.setWSSGenerationContextForTrustClient(gencont1);
// Generisches Sicherheitstoken abrufen
GenericSecurityToken token = (GenericSecurityToken) factory.newSecurityToken
(GenericSecurityToken.class, cbHandler1, "system.wss.generate.issuedToken");
QName Saml11ValueType = new QName(WSSConstants.SAML.SAML11_VALUE_TYPE);
token.setValueType(Saml11ValueType);
System.out.println("SAMLToken id = " + token.getId());
// Web-Service-Client initialisieren
EchoService12PortProxy echo = new EchoService12PortProxy();
echo._getDescriptor().setEndpoint(endpointURL);
// SOAPAction-Eigenschaften konfigurieren
BindingProvider bp = (BindingProvider) (echo._getDescriptor().getProxy());
Map<String, Object> requestContext = bp.getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
requestContext.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
requestContext.put(BindingProvider.SOAPACTION_URI_PROPERTY, "echoOperation");
// WSSGenerationContext initialisieren
WSSGenerationContext gencont = factory.newWSSGenerationContext();
gencont.add(token);
// Zeitmarke hinzufügen
WSSTimestamp timestamp = factory.newWSSTimestamp();
gencont.add(timestamp);
gencont.process(requestContext);
// Eingabeobjekt erstellen
EchoStringInput echoParm =
new com.ibm.was.wssample.sei.echo.ObjectFactory().createEchoStringInput();
echoParm.setEchoInput(input);
System.out.println(">> CLIENT: SEI Echo to " + endpointURL);
// Verarbeitung der Zeitmarke in der Antwortnachricht vorbereiten
WSSConsumingContext concont = factory.newWSSConsumingContext();
concont.add(WSSConsumingContext.TIMESTAMP);
concont.process(requestContext);
// Service aufrufen
response = echo.echoOperation(echoParm).getEchoResponse();
System.out.println(">> CLIENT: SEI Echo invocation complete.");
System.out.println(">> CLIENT: SEI Echo response is: " + response);
} catch (Exception e) {
System.out.println(">> CLIENT: ERROR: SEI Echo EXCEPTION.");
e.printStackTrace();
}
}
}