Sie können die APIs des Typs "GenericSecurityTokenFactory" verwenden, um ein SAML-Token,
das Sie erstellt haben, an das Modul "SAMLGenerateLoginModule" oder das Modul
"GenericIssuedTokenGenerateLoginModule" zu übergeben. Außerdem können Sie mit diesen
APIs SAML-Token abrufen, die
vom Modul "SAMLConsumeLoginModule" oder
"GenericIssuedTokenConsumeLoginModule" konsumiert werden.
Vorbereitende Schritte
Es wird vorausgesetzt, dass ein funktionierender Satz von
JAX-WS-Service-Client- und - Provider-Anwendungen vorhanden ist, dem Sie neue JAAS-Anmeldemodulklassen hinzufügen können.
Informationen zu diesem Vorgang
Mit dieser Task wird ein
SAML 1.1-Bearer-Token (Trägertoken) generiert. Dieses kann jedoch ohne großen Aufwand modifiziert werden, um
Sender-Vouches und die SAML-Version, die von der Laufzeitumgebung unterstützt wird, zu verwenden.
Obwohl Sie ein Anmeldemodul im Stack unterhalb von
"SAMLGenerateLoginModule" anordnen können, um ein von dieser Klasse erstelltes SAML-Token zu überprüfen,
ist es nicht möglich, ein auf diese Art und Weise gewonnenes SAML-Token zu modifizieren, es sei denn, das Token enthält keine digitale Signatur.
Wenn Sie ein SAML-Token modifizieren, das eine digitale Signatur enthält,
wird die XML für das SAML-Token entsprechend Ihren Aktualisierungen angepasst.
Weil das Token jedoch signiert wurde, bevor Sie es aktualisiert haben, schlägt die Signaturvalidierung beim Empfänger fehl.
Mit dieser Task wird ein
SAML 1.1-Bearer-Token (Trägertoken) generiert. Sie können jedoch jede SAML-Version und jeden Typ verwenden,
die von der Laufzeitumgebung unterstützt werden.
Weitere Informationen zum Erstellen und Modifizieren von
SAML-Token mit den APIs des Typs
"GenericSecurityTokenFactory" finden Sie im Artikel
SAML-Anwendungen entwickeln. Weitere Informationen darüber,
wie Sie das Token in den Clientanforderungskontext aufnehmen anstatt ein JAAS-Anmeldemodul zu verwenden,
finden Sie in der Beschreibung der Konstanten
"com.ibm.wsspi.wssecurity.token.tokenHolder" und "com.ibm.wsspi.wssecurity.token.enableCaptureTokenContext" in der Dokumentation zu
"com.ibm.wsspi.wssecurity.core.Constants".
Weil das Generatorbeispiel nicht einfach für die Verwendung eines HoK (Holder-of-Key) geändert werden kann,
wird am Ende dieser Task ein Beispiel der Methode
"createSamlToken()" aufgeführt, das spezifisch für
SAML-Holder-of-Key ist.
Vorgehensweise
- Erstellen Sie das folgende Generator-JAAS-Anmeldemodul und machen Sie es für Ihren Anwendungscode verfügbar.
package test.tokens;
import java.util.ArrayList;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken;
import com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory;
import com.ibm.wsspi.wssecurity.saml.config.CredentialConfig;
import com.ibm.wsspi.wssecurity.saml.config.ProviderConfig;
import com.ibm.wsspi.wssecurity.saml.config.RequesterConfig;
import com.ibm.wsspi.wssecurity.saml.data.SAMLAttribute;
import com.ibm.wsspi.wssecurity.core.config.KeyInformationConfig;
import com.ibm.wsspi.wssecurity.core.config.KeyStoreConfig;
import com.ibm.websphere.wssecurity.wssapi.WSSUtilFactory;
public class MySamlGenerator implements LoginModule {
private Map _sharedState;
private Map _options;
private CallbackHandler _handler;
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options) {
this._handler = callbackHandler;
this._sharedState = sharedState;
this._options = options;
}
public boolean login() throws LoginException {
GenericSecurityTokenFactory factory = null;
try {
factory = GenericSecurityTokenFactory.getInstance();
} catch (Exception e) {
throw new LoginException(e.toString());
}
if (factory == null) {
throw new LoginException("GenericSecurityTokenFactory.getInstance() returned null");
}
SAMLToken myToken = null;
try {
myToken = createSamlToken();
} catch (Exception e) {
throw new LoginException(e.toString());
}
if (myToken == null) {
throw new LoginException("myToken is null");
}
//Nehmen Sie das Token in eine Liste für den gemeinsamen Status (Shared State) auf, wo es
//für andere Anmeldemodule im Stack verfügbar ist
factory.putGeneratorTokenToSharedState(_sharedState, myToken);
return true;
}
private SAMLToken createSamlToken() throws Exception {
//SAML-Bearer-Beispiel
SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV11Token11);
RequesterConfig reqData = samlFactory.newBearerTokenGenerateConfig();
reqData.setAuthenticationMethod("Password"); //Authentication method for Assertion
ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");
CredentialConfig cred = samlFactory.newCredentialConfig ();
cred.setRequesterNameID("Alice"); // SAML NameIdentifier
//Einige SAML-Attribute hinzufügen:
SAMLAttribute attribute = new SAMLAttribute
("email", new String[] {"joe@websphere"},null, "WebSphere", "email", "joe");
ArrayList<SAMLAttribute> al = new ArrayList<SAMLAttribute>();
al.add(attribute);
attribute = new SAMLAttribute("Membership",
new String[] {"Super users", "My team"}, null, null, null, null );
al.add(attribute);
cred.setSAMLAttributes(al);
SAMLToken samlToken = samlFactory.newSAMLToken(cred, reqData, samlIssuerCfg);
return samlToken;
}
public boolean logout() throws LoginException {
return false;
}
public boolean abort() throws LoginException {
return false;
}
public boolean commit() throws LoginException {
return true;
}
}
- Erstellen Sie das folgende Konsumenten-JAAS-Anmeldemodul und machen Sie es für Ihren Anwendungscode verfügbar.
package test.tokens;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import javax.xml.namespace.QName;
import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken;
import com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory;
import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken;
public class MySamlConsumer implements LoginModule {
private Map _sharedState;
private Map _options;
private CallbackHandler _handler;
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options) {
this._handler = callbackHandler;
this._sharedState = sharedState;
this._options = options;
}
public boolean login() throws LoginException {
GenericSecurityTokenFactory factory = null;
try {
factory = GenericSecurityTokenFactory.getInstance();
} catch (Exception e) {
throw new LoginException(e.toString());
}
if (factory == null) {
throw new LoginException("GenericSecurityTokenFactory.getInstance() returned null");
}
//Das von "GenericIssuedConsumeLoginModule" konsumierte Token abrufen
SecurityToken myToken = factory.getConsumerTokenFromSharedState(_sharedState, new QName(SAMLTokenFactory.WssSamlV11Token11));
if (myToken == null) {
throw new LoginException("myToken is null");
}
if (myToken instanceof SAMLToken) {
//SAML-Token mit SAML-APIs untersuchen
SAMLToken samlToken = (SAMLToken)myToken;
String id = samlToken.getSamlID();
String subjectDns = samlToken.getSubjectDNS();
//...
} else {
throw new LoginException("Did not receive a SAML token");
}
return true;
}
public boolean logout() throws LoginException {
return false;
}
public boolean abort() throws LoginException {
return false;
}
public boolean commit() throws LoginException {
return true;
}
}
- Erstellen Sie eine JAAS-Anmeldekonfiguration.
- Wählen Sie in der Administrationskonsole
aus.
- Klicken Sie unter "Authentifizierung" auf
.
- Erstellen Sie den SAML-Tokengenerator.
- Klicken Sie auf Neu, und geben Sie unter "Alias"
test.generate.saml ein.
- Klicken Sie unter "JAAS-Anmeldemodule" auf
Neu und geben Sie unter "Name der Modulklasse"
den Namen test.tokens.MySamlGenerator ein.
Wählen Sie
Proxy für Anmeldemodul verwenden aus und klicken Sie auf
OK.
- Klicken Sie auf Neu, und geben Sie unter "Name der Modulklasse" den Namen
com.ibm.ws.wssecurity.wssapi.token.impl.SAMLGenerateLoginModule ein.
Klicken Sie auf OK.
- Erstellen Sie den SAML-Tokenkonsumenten.
- Klicken Sie im Navigationspfad auf
JAAS - Systemanmeldungen, um zur Seite "JAAS-Systemanmeldungen" zurückzukehren.
- Klicken Sie auf Neu, und geben Sie unter "Alias"
test.consume.saml ein.
- Klicken Sie unter "JAAS-Anmeldemodule" auf
Neu und geben Sie unter "Name der Modulklasse"
den Namen com.ibm.ws.wssecurity.wssapi.token.impl.SAMLConsumeLoginModule ein.
Wählen Sie
Proxy für Anmeldemodul verwenden aus und klicken Sie auf
OK.
- Klicken Sie auf Speichern.
- Konfigurieren Sie den SAML-Tokengenerator für die Verwendung der neuen JAAS-Anmeldekonfiguration.
- Öffnen Sie in der Administrationskonsole
die Bindungskonfiguration, die geändert werden soll.
- Wählen Sie aus.
- Wählen Sie unter "Authentifizierungstoken" das abgehende SAML-Token aus, das Sie ändern möchten.
- Wählen Sie unter "JAAS-Anmeldung"
test.generate.saml aus.
- Konfigurieren Sie den SAML-Tokenkonsumenten für die Verwendung der neuen JAAS-Anmeldekonfiguration.
- Öffnen Sie in der Administrationskonsole
die Bindungskonfiguration, die geändert werden soll.
- Wählen Sie aus.
- Wählen Sie unter
"Authentifizierungstoken" das eingehende SAML-Token aus, das Sie ändern möchten.
- Wählen Sie unter "JAAS-Anmeldung"
test.consume.saml aus.
- Klicken Sie auf Speichern.
- Starten Sie den Anwendungsserver erneut, um die JAAS-Konfigurationsänderungen anzuwenden.
- Testen Sie den Service.
Beispiel
Das folgende Beispiel veranschaulicht die Methode
"createSamlToken()", mit der ein asymmetrisches SAML 2.0-HoK-Token (Holder-of-Key) erstellt wird.
private SAMLToken createSamlToken() throws Exception {
SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV20Token11);
RequesterConfig reqData = samlFactory.newAsymmetricHolderOfKeyTokenGenerateConfig();
reqData.setAuthenticationMethod("Password"); //Authentifizierungsmethode für die Zusicherung
ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");
CredentialConfig cred = samlFactory.newCredentialConfig ();
cred.setRequesterNameID("Alice"); // SAML-Namens-ID
// (Optional) Wenn Sie Keystore- und Schlüsseleigenschaften festlegen möchten,
// die von den Eigenschaften in der Datei "SAMLIssuerConfig.properties" abweichen,
// müssen Sie die Keystore-, Truststore- und Aliasinformationen im Objekt
// ProviderConfig zurücksetzen.
KeyInformationConfig kic = samlFactory.newKeyInformationConfig("private_key","keypass","CN=Private");
KeyStoreConfig ksc = samlFactory.newKeyStoreConfig("jks","/keystores/myKeystore.ks","storepass");
samlIssuerCfg.setKeyStoreConfig(ksc); //Keystore mit dem privaten Schlüssel
samlIssuerCfg.setTrustStoreConfig(ksc); //Keystore mit dem öffentlichen Schlüssel
// Legen Sie den Alias für das öffentliche Zertifikat fest, das im Truststore vorhanden sein muss.
// Für diesen Alias darf kein Kennwort erforderlich sein.
reqData.setKeyAliasForRequester("public_cert");
SecurityToken samlToken = samlFactory.newSAMLToken(cred, reqData, samlIssuerCfg);
// Privaten Schlüssel aus dem Keystore abrufen
WSSUtilFactory wssufactory = WSSUtilFactory.getInstance();
java.security.KeyStore ks = wssufactory.getKeyStore("jks","/keystores/myKeystore.ks",
"storepass".toCharArray());
java.security.Key privateKey = ks.getKey("private_key", "keypass".toCharArray());
// Den privaten Schlüssel dem Token hinzufügen, damit das Token verwendet werden kann,
// um Elemente in einer SOAP-Nachricht zu signieren. ((com.ibm.ws.wssecurity.wssapi.token.impl.SecurityTokenImpl)samlToken).
setKey(SecurityToken.SIGNING_KEY, privateKey); ((com.ibm.ws.wssecurity.wssapi.token.impl.SecurityTokenImpl)samlToken).
setKey(SecurityToken.DECRYPTING_KEY, privateKey);
return samlToken;
}