É possível usar as APIs GenericSecurityTokenFactory para passar um token SAML criado para os módulos
SAMLGenerateLoginModule
ou GenericIssuedTokenGenerateLoginModule. Também é possível usar essas APIs para obter tokens SAML que são consumidos pelos módulos SAMLConsumeLoginModule
ou GenericIssuedTokenConsumeLoginModule.
Antes de Iniciar
Você deverá ter um conjunto de funções de aplicativos clientes e provedores de serviço do JAX-WS no qual poderão ser incluídas classes de módulo de login do JAAS.
Sobre Esta Tarefa
Esta tarefa gera um token de acesso SAML 1.1, mas pode ser facilmente modificada para usar
sender-vouches e qualquer versão do SAML suportada pelo ambiente de tempo de execução.
Apesar de ser possível empilhar um módulo de login sob
SAMLGenerateLoginModule para inspecionar um token SAML que foi criado por essa classe, não é possível modificar o token SAML que é obtido dessa maneira, a menos que o token não contenha uma assinatura digital.
Se você modificar um token SAML que contém uma assinatura digital, o XML do token SAML será ajustado para suas atualizações, mas porque o token foi assinado antes de ser atualizado, a validação da assinatura falhará no destinatário.
Essa tarefa gera um token de acesso SAML 1.1, mas não é possível usar nenhuma versão e tipo SAML suportados pelo ambiente de tempo de execução. Para obter informações adicionais sobre como criar e modificar tokens SAML com as APIs
GenericSecurityTokenFactory, consulte Desenvolvendo Aplicativos SAML. Para obter informações adicionais sobre como colocar o token no contexto de solicitação do cliente em vez de usar um módulo de login do JAAS, consulte
as constantes com.ibm.wsspi.wssecurity.token.tokenHolder e
com.ibm.wsspi.wssecurity.token.enableCaptureTokenContext em
com.ibm.wsspi.wssecurity.core.Constants.
Como o exemplo de gerador não pode ser facilmente modificado para usar holder-of-key, um exemplo
do método createSamlToken() específico para o holder-of-key SAML é fornecido no término
desta tarefa.
Procedimento
- Crie o módulo de login do JAAS a seguir e disponibilize-o para o código do aplicativo.
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");
}
//Put the token in a list on the shared state where it will be available to be used by
//stacked login modules
factory.putGeneratorTokenToSharedState(_sharedState, myToken);
return true;
}
private SAMLToken createSamlToken() throws Exception {
//SAML Bearer example
SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV11Token11);
RequesterConfig reqData = samlFactory.newBearerTokenGenerateConfig();
reqData.setAuthenticationMethod("Password"); //Método de autenticação para Asserção
ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");
CredentialConfig cred = samlFactory.newCredentialConfig ();
cred.setRequesterNameID("Alice"); // NameIdentifier do SAML
//Add some SAML attributes:
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;
}
}
- Crie o módulo de login do JAAS do consumidor a seguir e disponibilize-o ao código do aplicativo.
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");
}
//Get the token that was consumed by the GenericIssuedConsumeLoginModule
SecurityToken myToken = factory.getConsumerTokenFromSharedState(_sharedState, new QName(SAMLTokenFactory.WssSamlV11Token11));
if (myToken == null) {
throw new LoginException("myToken is null");
}
if (myToken instanceof SAMLToken) {
//Examine the SAML token with SAML APIs
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;
}
}
- Crie uma configuração de login do JAAS.
- No console administrativo, acesse .
- Sob Autenticação, acesse .
- Crie o gerador de token SAML.
- Clique em Novo e, sob Alias, insira test.generate.saml.
- Sob Módulos de Login do JAAS, clique em Novo e sob Nome da Classe do Módulo, insira test.tokens.MySamlGenerator.
Selecione Usar Proxy do Módulo de Login e clique em OK.
- Clique em Novo e, sob Nome da Classe do Módulo, insira
com.ibm.ws.wssecurity.wssapi.token.impl.SAMLGenerateLoginModule.
Clique OK.
- Crie o consumidor de token SAML.
- Clique em JAAS - Logins do sistema na trilha de navegação para retornar à página de logins do sistema JAAS.
- Clique em Novo e, sob Alias, insira test.consume.saml.
- Sob Módulos de Login do JAAS, clique em Novo e, sob Nome da Classe do Módulo, insira
com.ibm.ws.wssecurity.wssapi.token.impl.SAMLConsumeLoginModule.
Selecione Usar Proxy do Módulo de Login e clique em OK.
- Clique em Salvar.
- Configure o gerador de token SAML para usar a nova configuração de login do
JAAS.
- No console administrativo, abra a configuração de ligação que deseja alterar.
- Selecione .
- Em Tokens de Autenticação, selecione o token de saída SAML que deseja alterar.
- Sob Login do JAAS, selecione test.generate.saml.
- Configure o consumidor de token SAML para usar a nova configuração do
JAAS.
- No console administrativo, abra a configuração de ligação que deseja alterar.
- Selecione .
- Em Tokens de Autenticação, selecione o token de entrada SAML que deseja alterar.
- Sob Login do JAAS, selecione test.consume.saml.
- Clique em Salvar.
- Reinicie o servidor de aplicativos para aplicar as mudanças na configuração do JAAS.
- Teste o serviço.
Exemplo
O exemplo a seguir ilustra o método createSamlToken() para criar um
token holder-of-key assimétrico do
SAML 2.0.
private SAMLToken createSamlToken() throws Exception {
SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance (SAMLTokenFactory.WssSamlV20Token11);
RequesterConfig reqData = samlFactory.newAsymmetricHolderOfKeyTokenGenerateConfig();
reqData.setAuthenticationMethod("Password"); //Método de autenticação para Asserção
ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");
CredentialConfig cred = samlFactory.newCredentialConfig ();
cred.setRequesterNameID("Alice"); // NameIdentifier do SAML
// (Optional) If you want to use keystore and key properties other than what
// is set in the SAMLIssuerConfig.properties file, reset the keystore,
// trust store and alias information in the ProviderConfig object.
KeyInformationConfig kic = samlFactory.newKeyInformationConfig("private_key","keypass","CN=Private");
KeyStoreConfig ksc = samlFactory.newKeyStoreConfig("jks","/keystores/myKeystore.ks","storepass");
samlIssuerCfg.setKeyStoreConfig(ksc); //keystore that holds the private key
samlIssuerCfg.setTrustStoreConfig(ksc); //keystore that holds the public key
// Set the alias for the public certificate that must exist in the trust store.
// This alias must not require a password.
reqData.setKeyAliasForRequester("public_cert");
SecurityToken samlToken = samlFactory.newSAMLToken(cred, reqData, samlIssuerCfg);
// Get the private key from the key store
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());
// Add the private key to the token so that the token can be used to sign
// elements in a SOAP message. ((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;
}