Puede utilizar las API GenericSecurityTokenFactory para pasar una señal SAML que ha creado para los módulos SAMLGenerateLoginModule o GenericIssuedTokenGenerateLoginModule. También puede utilizar estas API para obtener señales SAML que los módulos SAMLConsumeLoginModule o GenericIssuedTokenConsumeLoginModule consumen.
Antes de empezar
Debe tener un conjunto de aplicaciones de cliente y proveedor de servicio JAX-WS en funcionamiento donde añadir las clases de módulo de inicio de sesión JAAS nuevas.
Acerca de esta tarea
Esta tarea genera una señal de transporte de SAML 1.1, pero puede
ser modificada fácilmente para utilizar sender-vouches y cualquier versión
de SAML soportada por el entorno de ejecución.
Aunque puede apilar un
módulo de inicio de sesión bajo SAMLGenerateLoginModule para inspeccionar
una señal SAML creada por esa clase, no puede modificar la señal SAML
obtenida de este modo a menos que la señal no contenga una firma digital.
Si modifica una señal SAML que contiene una firma digital, el XML para la señal SAML se ajustará para las actualizaciones; pero, puesto que la señal se ha firmado antes de la actualización, la validación de la firma fallará en el receptor.
Esta tarea genera una señal de portador SAML 1,1, pero puede utilizar cualquier versión de SAML y el tipo que esté soportado por el entorno de ejecución. Para obtener más información sobre la creación y modificación de señales SAML con las API GenericSecurityTokenFactory, consulte Desarrollo de aplicaciones SAML. Para obtener más información sobre cómo colocar la señal en el contexto de la solicitud del cliente en lugar de utilizar un módulo de inicio de sesión JAAS, consulte la información sobre las constantes com.ibm.wsspi.wssecurity.token.tokenHolder y com.ibm.wsspi.wssecurity.token.enableCaptureTokenContext en com.ibm.wsspi.wssecurity.core.Constants.
Debido a que el ejemplo de generador no se puede modificar
fácilmente para utilizar el poseedor de clave, al final de esta tarea se
proporciona un ejemplo del método createSamlToken() que es específico para
el poseedor de clave de SAML.
Procedimiento
- Cree el módulo de inicio de sesión JAAS de generador siguiente y
haga que esté disponible para el código de aplicación.
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");
}
//Coloque la señal en una lista en el estado compartido donde estará disponible para ser utilizada por los
//módulos de inicio de sesión apilados
factory.putGeneratorTokenToSharedState(_sharedState, myToken);
return true;
}
private SAMLToken createSamlToken() throws Exception {
//Ejemplo de portador SAML
SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV11Token11);
RequesterConfig reqData = samlFactory.newBearerTokenGenerateConfig();
reqData.setAuthenticationMethod("Password"); //Método de autenticación para la Assertion
ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");
CredentialConfig cred = samlFactory.newCredentialConfig ();
cred.setRequesterNameID("Alice"); // SAML NameIdentifier
//Añadir algunos atributos SAML:
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;
}
}
- Cree el módulo de inicio de sesión JAAS de consumidor siguiente y póngalo a disposición para el código de aplicación.
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");
}
//Obtener la señal consumida por GenericIssuedConsumeLoginModule
SecurityToken myToken = factory.getConsumerTokenFromSharedState(_sharedState, new QName(SAMLTokenFactory.WssSamlV11Token11));
if (myToken == null) {
throw new LoginException("myToken is null");
}
if (myToken instanceof SAMLToken) {
//Examinar la señal SAML con las API SAML
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;
}
}
- Crear una configuración de inicio de sesión JAAS.
- En la consola administrativa, vaya a .
- En autenticación, vaya a .
- Cree el generador de señales SAML.
- Pulse Nuevo y, en Alias, especifique test.generate.saml.
- En Módulos de inicio de sesión JAAS, pulse Nuevo y, en Nombre de clase de módulo, especifique test.tokens.MySamlGenerator.
Seleccione Utilizar proxy de módulo de inicio de sesión y pulse Aceptar.
- Pulse Nuevo y, en Nombre de clase de módulo, especifique com.ibm.ws.wssecurity.wssapi.token.impl.SAMLGenerateLoginModule.
Pulse Aceptar.
- Cree el consumidor de señal SAML.
- Pulse JAAS - Inicios de sesión de sistema en los rastros de navegación para volver a la página de inicios de sesión del sistema
JAAS.
- Pulse Nuevo y, en Alias, especifique test.consume.saml.
- En Módulos de inicio de sesión JAAS, pulse Nuevo y, en Nombre de clase de módulo, especifique com.ibm.ws.wssecurity.wssapi.token.impl.SAMLConsumeLoginModule.
Seleccione Utilizar proxy de módulo de inicio de sesión y pulse Aceptar.
- Pulse Guardar.
- Configure el generador de señales SAML que debe utilizar la nueva configuración de inicio de sesión JAAS.
- En la consola administrativa, abra la configuración de enlaces que desea cambiar.
- Seleccione .
- En Señales de autenticación, seleccione la señal SAML de salida que desee cambiar.
- En Inicio de sesión JAAS, seleccione test.generate.saml.
- Configure el consumidor de señal SAML que debe utilizar la nueva configuración de JAAS.
- En la consola administrativa, abra la configuración de enlaces que desea cambiar.
- Seleccione .
- En Señales de autenticación, seleccione la señal de entrada SAML que desea cambiar.
- En Inicio de sesión JAAS, seleccione test.consume.saml.
- Pulse Guardar.
- Reinicie el servidor de aplicaciones para aplicar los cambios de configuración JAAS.
- Pruebe el servicio.
Ejemplo
El ejemplo siguiente muestra el método createSamlToken() para
crear una señal de poseedor de clave asimétrica para SAML 2.0.
private SAMLToken createSamlToken() throws Exception {
SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV20Token11);
RequesterConfig reqData = samlFactory.newAsymmetricHolderOfKeyTokenGenerateConfig();
reqData.setAuthenticationMethod("Password"); //Método de autenticación para aserción
ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");
CredentialConfig cred = samlFactory.newCredentialConfig ();
cred.setRequesterNameID("Alice"); // SAML NameIdentifier
// (Opcional) Si desea utilizar propiedades de almacén de claves y de clave distintas de lo que
// está establecido en el archivo SAMLIssuerConfig.properties, inicialice la información de
// almacén de claves, almacén de confianza y de alias en el objeto ProviderConfig.
KeyInformationConfig kic = samlFactory.newKeyInformationConfig("private_key","keypass","CN=Private");
KeyStoreConfig ksc = samlFactory.newKeyStoreConfig("jks","/keystores/myKeystore.ks","storepass");
samlIssuerCfg.setKeyStoreConfig(ksc); //almacén de claves que contiene la clave privada
samlIssuerCfg.setTrustStoreConfig(ksc); //almacén de claves que contiene la clave pública
// Defina el alias del certificado público que debe existir en el almacén de confianza.
// Este alias no debe necesitar una contraseña.
reqData.setKeyAliasForRequester("public_cert");
SecurityToken samlToken = samlFactory.newSAMLToken(cred, reqData, samlIssuerCfg);
// Obtener la clave privada a partir del almacén de claves
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());
// Añadir la clave privada a la señal para que la señal se pueda utilizar para firmar
// elementos en un mensaje SOAP. ((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;
}