Substituindo o método de autenticação do consumidor de UsernameToken usando um módulo de login do JAAS empilhado

Por padrão, o consumidor de UsernameToken de segurança dos serviços da web, UNTConsumeLoginModule, sempre valida o nome de usuário e a senha contidos no token com relação ao registro do WebSphere. É possível usar as SPIs fornecidas pelo GenericSecurityTokenFactory para efetuar bypass nesse método de autenticação.

Sobre Esta Tarefa

Se desejar substituir o método de autenticação usado pelo UNTConsumeLoginModule, você deverá fornecer seu próprio módulo de login do JAAS customizado para fazer a autenticação. O módulo de login customizado é empilhado em UNTConsumeLoginModule em uma configuração do JAAS customizada. O UNTConsumeLoginModule consome e valida o XML do token. A validação dos valores fornecidos para nome de usuário e senha é adiada para o módulo de login empilhado customizado.

Como o uso de UNTConsumeLoginModule carrega a suposição de que o nome de usuário e a senha serão autenticados, são colocados mais requisitos em um módulo de login empilhado que deve executar esta função do que são colocados em módulos de login que somente devem fornecer a funcionalidade de token dinâmico.

Para indicar para UNTConsumeLoginModule que ele não deve autenticar o nome de usuário e a senha, deve-se configurar a propriedade a seguir no manipulador de retorno de chamada configurado:

com.ibm.wsspi.wssecurity.token.UsernameToken.authDeferred=true

Como a maioria dos módulos de login de Web Services Security, o UNTConsumeLoginModule sempre coloca o token consumido no mapa de estado compartilhado ao qual todos os módulos de login na pilha têm acesso. Quando authDeferred=true é especificado, na fase de confirmação, UNTConsumeLoginModule assegura que o mesmo objeto UsernameToken que foi colocado originalmente no estado compartilhado tenha sido colocado em outro local no estado compartilhado. Se este objeto UsernameToken não puder ser localizado, ocorrerá uma LoginException. Portanto, não é possível apenas configurar authDeferred=true no manipulador de retorno de chamada sem que um módulo de login acompanhante retorne o token para o estado compartilhado.

Procedimento

  1. Desenvolva um módulo de login do JAAS para executar a autenticação e disponibilize-o ao código do aplicativo. Este novo módulo de login é empilhado abaixo do com.ibm.ws.wssecurity.wssapi.token.impl.UNTConsumeLoginModule.

    Este módulo de login deve:

    1. Use o método a seguir para obter o UsernameToken que o UNTConsumeLoginModule consome.
      UsernameToken unt = (UsernameToken)factory.getConsumerTokenFromSharedState(sharedState,UsernameToken.ValueType);
      Nesse exemplo de código, factory é uma instância de com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory.
    2. Verifique o nome de usuário e a senha da maneira que você escolher.

      É possível chamar unt.getUsername() e unt.getPassword() para obter o nome de usuário e a senha.

      Agora, o módulo de login deverá lançar uma LoginException se houver algum erro de autenticação.

    3. Coloque o UsernameToken, que foi obtido na subetapa anterior, de volta no estado compartilhado.

      Use o método a seguir para colocar UsernameToken de volta no estado compartilhado.

      factory.putAuthenticatedTokenToSharedState(sharedState, unt);

    A seguir há um módulo de login de exemplo:

    package test.tokens;
    
    import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
    import com.ibm.websphere.wssecurity.wssapi.WSSUtilFactory;
    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 com.ibm.websphere.wssecurity.wssapi.token.UsernameToken;
    
    import java.util.ArrayList;
    
    import com.ibm.wsspi.security.registry.RegistryHelper;
    import com.ibm.websphere.security.UserRegistry;
    
    public class MyUntAuthenticator 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 {
        //For the sake of readability, this login module does not
        //protect against all NPE's
    
        GenericSecurityTokenFactory factory = null;
        WSSUtilFactory utilFactory = null;
        try {
          factory = GenericSecurityTokenFactory.getInstance();
          utilFactory = WSSUtilFactory.getInstance();
        } catch(Exception e) {
          throw new LoginException(e.toString());
        }
        if (factory == null) {
          throw new LoginException("GenericSecurityTokenFactory.getInstance() returned null");
        }
    
        UsernameToken unt = (UsernameToken)factory.getConsumerTokenFromSharedState(this._sharedState,UsernameToken.ValueType);
    
        String username = unt.getUsername();
        char [] password = unt.getPassword();
    
        //autenticar nome de usuário e senha 
        //to validate a PasswordDigest password 
        //String pw = yourCodeToLookUpPasswordForUsername(username);
        //boolean match = utilFactory.verifyDigestedPassword(unt, pw.toCharArray());
        //if (!match) throw new LoginException("Digested passwords do not match");
        //Example:
        try {
          simpleUserGroupCheck(username, password, "cn=group1,o=ibm,c=us");
        } catch(Exception e) {
          LoginException le = new LoginException(e.getMessage());
          le.initCause(e);
          throw le;
        }
    
        //Colocar token autenticado no estado compartilhado
        factory.putAuthenticatedTokenToSharedState(this._sharedState, unt);
    
        return true;
      }
    
      private boolean simpleUserGroupCheck(String username, char [] password, String group) throws Exception {
        String allowedGroup = null;
    
        //get the default user registry
        UserRegistry user_reg = RegistryHelper.getUserRegistry(null);
    
        //authenticate the user against the user registry
        user_reg.checkPassword(username, new String(password));
    
        //get the list of groups that the user belongs to
        java.util.List<String> groupList = user_reg.getGroupsForUser(username);
    
        //you can either use a hard-coded group
        allowedGroup = group;
    
        //or get the value from your own custom property on the callback handler
        //WSSUtilFactory util = WSSUtilFactory.getInstance();
        //Map map = util.getCallbackHandlerProperties(this._handler);
        //allowedGroup = (String) map.get("MY_ALLOWED_GROUP_1");
    
        //check if the user belongs to an allowed group
        if (!groupList.contains(allowedGroup)) {
          throw new LoginException("user ["+username+"] is not in allowed group ["+allowedGroup+"]");
        }
        return true;
    }
      //implementar o restante dos métodos requeridos pela
      //interface LoginModule
    }
  2. Crie uma nova configuração de login do JAAS.
    1. No console administrativo, selecione Segurança > Segurança Global.
    2. Em Autenticação, selecione Java Authentication and Authorization Service.
    3. Selecione Logins do sistema.
    4. Clique em Novo e especifique Alias = test.consume.unt.
    5. Clique em Novo e selecione Nome de classe do módulo = com.ibm.ws.wssecurity.wssapi.token.impl.UNTConsumeLoginModule
    6. Clique em Novo e especifique Nome de classe do módulo = test.tokens.MyUntAuthenticator
    7. Selecione Usar proxy do módulo de login.
    8. Clique em OK e em SALVAR.
  3. Configure o consumidor de token UsernameToken para usar a nova configuração de JAAS.
    1. Abra a configuração de ligações que deseja alterar.

      No console administrativo, selecione Segurança dos serviços da web > Autenticação e proteção.

    2. Em Tokens de Autenticação, selecione o token de entrada UsernameToken que deseja alterar.
    3. Selecione Login do JAAS = test.consume.unt.
  4. Configure a propriedade necessária no manipulador de retorno de chamada que está configurado para o consumidor UsernameToken.
    1. Clique em Manipulador de Retorno de Chamada.
    2. Inclua a propriedade customizada com.ibm.wsspi.wssecurity.token.UsernameToken.authDeferred=true.
    3. Clique OK.
  5. Clique em SALVAR.
  6. Reinicie o servidor de aplicativos para aplicar as mudanças na configuração do JAAS.
  7. Teste o serviço.

Ícone que indica o tipo de tópico Tópico de Tarefa



Ícone de registro de data e hora Última atualização: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=twbs_replace_authmethod_usernametoken
Nome do arquivo: twbs_replace_authmethod_usernametoken.html