O gerador e o consumidor de token emitidos genericamente,
GenericIssuedTokenGenerateLoginModule e
GenericIssuedTokenConsumeLoginModule, podem ser usados em conjunto com as
SPIs GenericSecurityTokenFactory e GenericSecurityToken para implementar
uma solução de ponta a ponta para um token customizado. A geração e o
consumo de tokens customizados com os Módulos de login de emissão genérica
podem ser feitos com políticas e ligações ou WSSAPIs.
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
Conclua as etapas a seguir se desejar ativar um conjunto de
aplicativos clientes e provedores de serviço do JAX-WS para usar um token
customizado.
Nestas etapas, MyToken é o nome do token que está sendo criado.
Após concluir esta tarefa:
- Dois módulos de login do JAAS serão criados, um para gerar o token e
um para consumi-lo.
- O token será gerado e consumido com assistência do consumidor e do
gerador de token emitido genericamente.
- Em seguida, as restrições de segurança serão aplicadas aos aplicativos
com conjuntos de políticas e ligações.
Procedimento
- Crie o seguinte módulo de login do JAAS do gerador e
disponibilize-o ao código do aplicativo
package test.tokens;
import java.util.ArrayList;
import java.util.HashMap;
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.soap.SOAPFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.namespace.QName;
import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken;
public class MyCustomGenerator 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");
}
SecurityToken myToken = null;
try {
SOAPElement tokenElement = createCustomElement(factory);
myToken = factory.getToken(tokenElement, new
QName("http://www.acme.com","MyToken"));
} 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 SOAPElement createCustomElement(GenericSecurityTokenFactory gstFactory) throws Exception {
/*
<acme:MyToken xmlns:acme="http://www.acme.com"
xmlns:utl="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" utl:Id="cust_3">
<acme:EMail>joe.smith@acme.com</acme:EMail>
</acme:MyToken>
*/
SOAPFactory factory = SOAPFactory.newInstance();
//Create the MyToken element
SOAPElement tokElement = factory.createElement("MyToken", "acme", "http://www.acme.com");
//Add the Id attribute
tokElement.addAttribute(new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Id", "utl"), gstFactory.createUniqueId());
//Create the Email element
SOAPElement emailElement = factory.createElement("Email", "acme", "http://www.acme.com");
emailElement.addTextNode("joe.smith@acme.com");
//Add the EMail element to the MyToken
tokElement.addChildElement(emailElement);
return tokElement;
}
public boolean logout() throws LoginException {
return false;
}
public boolean abort() throws LoginException {
return false;
}
public boolean commit() throws LoginException {
return true;
}
}
- Crie o seguinte módulo de login do JAAS do consumidor e
disponibilize-o ao código do aplicativo
package test.tokens;
import java.util.Map;
import javax.xml.namespace.QName;
import org.apache.axiom.om.OMElement;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import com.ibm.websphere.wssecurity.callbackhandler.PropertyCallback;
import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken;
import com.ibm.wsspi.wssecurity.wssapi.OMStructure;
public class MyCustomConsumer implements LoginModule {
private CallbackHandler _handler;
private Map _sharedState;
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options) {
this._handler = callbackHandler;
this._sharedState = sharedState;
}
public boolean login() throws LoginException {
PropertyCallback propertyCallback = new PropertyCallback(null);
Callback[] callbacks = new Callback[] { propertyCallback};
try {
this._handler.handle(callbacks);
} catch (Exception e) {
throw new LoginException(e.toString());
}
//Get the GenericSecurityTokenFactory
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");
}
//Obtenha o token que foi consumido pelo GenericIssuedConsumeLoginModule
SecurityToken myToken = factory.getConsumerTokenFromSharedState(_sharedState,
new QName("http://www.acme.com","MyToken"));
if (myToken == null) {
throw new LoginException("no token");
}
//Get the token's element
Object obj = myToken.getXML();
if (obj == null) {
throw new LoginException("token is empty");
}
if (!(obj instanceof OMStructure)) {
throw new LoginException("XML is not OMStructure");
}
OMElement tokenElement = ((OMStructure)obj).getNode();
//you can use the org.apache.axis2.util.XMLUtils.toDOM method
//if you want to work with the a w3c.dom element instead of an
//Axiom element
//Do some processing on the contents of the token element
OMElement el = tokenElement.getFirstChildWithName(new QName("http://www.acme.com","Email"));
if (el == null) {
throw new LoginException("no email element");
}
String value = el.getText();
if (value != null && value.equals("joe.smith@acme.com")) {
return true;
} else {
throw new LoginException("email value is bad");
}
}
public boolean commit() throws LoginException {
return true;
}
public boolean logout() throws LoginException {
return false;
}
public boolean abort() throws LoginException {
return false;
}
}
- Create new JAAS login configurations.
- No console administrativo, selecione Segurança->Segurança global.
- Em Autenticação, selecione Java Authentication
and Authorization Service.
- Selecione Logins do sistema.
- Crie o gerador com o módulo customizado primeiro.
- Clique em Novo e, em seguida, especifique
Alias = test.generate.custom.
- Clique em Novo e, em seguida, especifique
Nome da classe do módulo =
test.tokens.MyCustomGenerator.
- Selecione Usar proxy do módulo de login.
- Clique OK.
- Clique em Novo e, em seguida, selecione
Nome da classe do módulo =
com.ibm.ws.wssecurity.wssapi.token.impl.GenericIssuedTokenGenerateLoginModule.
- Clique OK.
- Clique em JAAS - Logins do sistema.
- Crie o consumidor com o módulo customizado por último.
- Clique em Novo e, em seguida, especifique
Alias = test.consume.custom.
- Clique em Novo e, em seguida, selecione Nome da classe do módulo =
com.ibm.ws.wssecurity.wssapi.token.impl.GenericIssuedTokenConsumeLoginModule.
- Clique em Novo e, em seguida, especifique Nome da classe de módulo =
test.tokens.MyCustomConsumer.
- Selecione Usar proxy do módulo de login.
- Clique OK.
- Clique em Salvar.
- Crie o conjunto de políticas customizadas.
- No console administrativo, clique em Serviços > Conjuntos de políticas > Conjuntos de políticas de aplicativos.
- Clique em Novo e, em seguida,
especifique ACustomTokenPolicy.
- Dê um clique em Aplicar.
- Em Políticas, clique em Incluir > WS-Security.
- Editar o conjunto de políticas customizadas.
- No console administrativo, clique em WS-Security > Política Principal.
- Remova os elementos não desejados:
- Desmarque Incluir Registro de Data e Hora no Cabeçalho de Segurança.
- Desmarque Proteção no nível da mensagem.
- Inclua o token customizado.
- Clique em Solicitar políticas de token
- Clique em Incluir tipo de token > Customizado e, em seguida, especifique:
- Nome do token customizado = myToken
- Parte local = MyToken
- URI do namespace = http://www.acme.com
- Clique OK.
- Clique em Salvar.
- Configure o cliente para usar o conjunto de políticas
ACustomTokenPolicy.
- No console administrativo, clique em Serviços > Clientes de serviço.
- Clique no cliente de serviço desejado.
- Selecione o recurso no nível superior.
- Clique em Anexar Conjunto de Políticas.
- Selecione ACustomTokenPolicy
- Crie uma ligação customizada para o cliente.
- Selecione o recurso no nível superior novamente.
- Clique em Designar Ligação.
- Clique em Nova Ligação Específica do Aplicativo para
criar uma ligação específica do aplicativo.
- Especifique o nome da configuração de ligações.
nome: customTokenClientBinding
- Clique em Incluir > WS-Security.
Se o painel Principais ligações de política de segurança de
mensagem não for exibido, selecione Web Services Security.
- Configure as ligações customizadas do cliente.
- Selecione Autenticação e proteção > request:myToken.
- Selecione Login do JAAS = test.generate.custom.
- Dê um clique em Aplicar.
- Clique em Manipulador de Retorno de Chamada.
- Inclua a propriedade customizada passThroughToken=true.
- Configure o provedor para usar o conjunto de políticas ACustomTokenPolicy.
- No console administrativo, clique em Serviços > Provedores de serviços.
- Clique no provedor de serviços desejado.
- Selecione o recurso no nível superior.
- Clique em Anexar Conjunto de Políticas.
- Selecione ACustomTok enPolicy.
- Crie uma ligação customizada para o provedor.
- Selecione o recurso no nível superior novamente.
- Clique em Designar Ligação.
- Clique em Nova Ligação Específica do Aplicativo para
criar uma ligação específica do aplicativo.
- Especifique o nome da configuração de ligações.
customTokenProviderBinding
- Clique em Incluir > WS-Security.
Se o painel Principais Ligações de Política de Segurança de Mensagem não for exibido, selecione WS-Security.
- Configure as ligações customizadas para o provedor.
- Selecione Autenticação e proteção > request:myToken.
- Selecione Login do JAAS = test.consume.custom.
- Dê um clique em Aplicar.
- Clique em Manipulador de Retorno de Chamada.
- Inclua as propriedades customizadas passThroughToken=true e alwaysGeneric=true.
- Clique em Salvar para salvar suas alterações na configuração.
- 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 cabeçalho de Segurança do SOAP que é produzido quando o procedimento anterior é seguido.
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<acme:MyToken xmlns:acme="http://www.acme.com" xmlns:utl="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" utl:Id="cust_3">
<acme:Email>joe.smith@acme.com</acme:Email>
</acme:MyToken>
</wsse:Security>