3.4. Autenticação do Assunto
A Autenticação do Assunto requer um login JAAS. O processo de login consiste dos seguintes critérios:
- Um aplicativo inicia um
LoginContext
e passa o nome da configuração do login e umCallbackHandler
para popular os assuntosCallback
, conforme requerido pela configuraçãoLoginModule
s. - O
LoginContext
consulta oConfiguration
para carregar todos osLoginModules
incluídos na configuração de login nomeada. Caso tal nome não existir, a configuraçãoother
é usada como default. - O aplicativo invoca o método
LoginContext.login
. - O método de login invoca todos os
LoginModule
s carregados. Uma vez que cadaLoginModule
tenta autenticar o assunto, ele invoca o método de manuseio noCallbackHandler
associado para obter a informação requerida pelo processo de autenticação. A informação requerida é passada ao método de manuseio na forma de um array dos assuntosCallback
. No caso de êxito, osLoginModule
s associam os principais e credenciais relevantes ao assunto. - O
LoginContext
retorna o status de autenticação ao aplicativo. O sucesso é representado por um retorno de um método de login. A falha é representada através de um LoginException sendo lançado pelo método de login. - Caso a autenticação suceder, o aplicativo recupera o assunto autenticado usando o método
LoginContext.getSubject
. - Após o escopo da autenticação do assunto ser concluído, todos os principais e informações relacionadas associadas ao assunto pelo método
login
podem ser removidas pela invocação do métodoLoginContext.logout
.
A classe
LoginContext
fornece os métodos básicos para autenticação dos assuntos e oferece uma maneira de desenvolver um aplicativo que é independente da tecnologia de autenticação subjacente. O LoginContext
consulta um Configuration
para determinar os serviços de autenticação configurados a um aplicativo em particular. As classes LoginModule
representam os serviços de autenticação. Portanto, você pode plugar diferentes módulos de login num aplicativo sem a alteração do próprio aplicativo. Os seguintes códigos apresentam as etapas requeridas por um aplicativo para autenticar um assunto.
CallbackHandler handler = new MyHandler(); LoginContext lc = new LoginContext("some-config", handler); try { lc.login(); Subject subject = lc.getSubject(); } catch(LoginException e) { System.out.println("authentication failed"); e.printStackTrace(); } // Perform work as authenticated Subject // ... // Scope of work complete, logout to remove authentication info try { lc.logout(); } catch(LoginException e) { System.out.println("logout failed"); e.printStackTrace(); } // A sample MyHandler class class MyHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof NameCallback) { NameCallback nc = (NameCallback)callbacks[i]; nc.setName(username); } else if (callbacks[i] instanceof PasswordCallback) { PasswordCallback pc = (PasswordCallback)callbacks[i]; pc.setPassword(password); } else { throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); } } } }
Os desenvolvedores integram uma tecnologia de autenticação pela criação de uma implementação da interface
LoginModule
. Isto permite o administrador a plugar diferentes tecnologias de autenticação num aplicativo. Você pode encadear diversos LoginModule
s para permitir que mais de uma tecnologia de autenticação participe no processo de autenticação. Por exemplo, um LoginModule
pode executar uma autenticação baseada no nome/senha do usuário, enquanto que outro pode realizar a interface aos dispositivos de hardware tais como leituras de cartões smart ou autenticadores biométricos.
O ciclo de vida de um
LoginModule
é dirigido pelo objeto LoginContext
em relação ao cliente que cria e emite o método de login. O processo consiste de duas fases. As etapas do processo são:
- O
LoginContext
cria cada configuraçãoLoginModule
usando seu construtor sem argumento público. - Cada
LoginModule
é inicializado com uma chamada ao seu método inicializar. OSubject
argumento é garantido como não nulo. A assinatura do método inicializar é:public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
- O método
login
é chamado para iniciar o processo de autenticação. Por exemplo, a implementação do método pode perguntar ao usuário pelo nome e senha do usuário e então verificar a informação em relação aos dados stored num serviço de nomeação tal como o NIS ou LDAP. As implementações alternativas podem realizar a interface para cartões smart e dispositivo biométricos, ou simplesmente extrair a informação do usuário a partir de um sistema de operação subjacente. A validação da identidade do usuário por cadaLoginModule
é considerada fase 1 da autenticação JAAS. A assinatura do métodologin
éboolean login() throws LoginException
. UmLoginException
indica falha. Um valor de retorno verdadeiro indica que o método foi bem sucedido, onde um valor de retorno de falso indica que o módulo de login deve ser ignorado. - Caso a autenticação no geral
LoginContext
suceder, ocommit
é invocado em cadaLoginModule
. Caso a fase 1 suceder para oLoginModule
, o método de confirmação continua com a fase 2 e associa os principais relevantes, credenciais públicos e/ou credenciais privados com o assunto. Caso a fase 1 falhar para umLoginModule
, então ocommit
remove qualquer estado de autenticação stored anteriormente, tais como nomes e senhas de usuários. A assinatura do métodocommit
é:boolean commit() throws LoginException
. A falha em concluir a fase de confirmação é indicada pelo lançamento doLoginException
. Um retorno verdadeiro indica que o método sucedeu, onde um retorno falso indica que o módulo de login deve ser ignorado. - Caso a autenticação no geral
LoginContext
, então o métodoabort
é invocado em cadaLoginModule
. O métodoabort
remove ou destroi qualquer estado de autenticação criado pelos métodos inicializar ou login. A assinatura do métodoabort
éboolean abort() throws LoginException
. A falha em completar a faseabort
é indicada pelo lançamento de umLoginException
. Um retorno verdadeiro indica que o método sucedeu, onde um retorno falso indica que o módulo de login deve ser ignorado. - Com o objetivo de remover o estado de autenticação após êxito de login, o aplicativo invoca
logout
noLoginContext
. Isto em troca resulta numa invocação do métodologout
em cadaLoginModule
. O métodologout
remove os principais e credenciais originalmente associados com o assunto durante a operaçãocommit
. Os credenciais devem ser destruídos sob remoção. A assinatura do métodologout
é:boolean logout() throws LoginException
. A falha em concluir o processo de saída é indicado pelo lançamento umLoginException
. Um retorno verdadeiro indica que o método sucedeu, onde um retorno de falso indica que o módulo de login deve ser ignorado.
Quando um
LoginModule
precisa comunicar-se com o usuário para obter a informação de autenticação, ele usa um objeto CallbackHandler
. Os aplicativos implementam a interface CallbackHandler e passam isto ao LoginContext
, que envia a informação de autenticação diretamente aos módulos de login subjacente.
Os módulos de login usam o
CallbackHandler
para tanto obter a entrada de usuários, tais como uma senha ou PIN do cartão smart e para suprir informação aos usuários, tais como informação de status. Permitir que o aplicativo especifique o CallbackHandler
, os LoginModule
s subjacentes continuam independentes de maneiras diferentes dos aplicativos interagirem com os usuários. Por exemplo: uma implementação CallbackHandler
para um aplicativo GUI pode exibir uma janela para solicitar a entrada do usuário. Por outro lado, uma implementação CallbackHandler
para um ambiente não GUI, tal como um servidor do aplicativo, pode simplesmente obter a informação do credencial pelo uso de um API do servidor do aplicativo. A interface CallbackHandler possui um método de implementação:
void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException;
A interface
Callback
é a última classe de autenticação que vamos ver. Ela é uma interface tagging da qual diversas implementações default são fornecidas, incluindo o NameCallback
e PasswordCallback
usados num exemplo anterior. O LoginModule
usa um Callback
para solicitar informação requerida pelo mecanismo de autenticação. O LoginModule
s passa um array de Callback
s diretamente ao método CallbackHandler.handle
durante a fase de login de autenticação. Caso um callbackhandler
não entender como usar o objeto Callback
passado ao método de manuseio, ele lança um UnsupportedCallbackException
para anular a chamada de login.