Você está na página 1de 8

Segurana com JAAS

Aplicaes que restringem o acesso de usurios ou processos a apenas alguns de seus recursos so muito comuns; implementar esse tipo de controle de segurana, no entanto, no nada fcil e faz-lo de forma que a aplicao seja independente da tecnologia de segurana utilizada ainda mais difcil. exatamente isso que o JAAS (Java Authentication and Authorization Service) se prope a resolver. Conceitos Antes de descrever a API de autenticao e autorizao de Java, precisamos apresentar alguns conceitos: Autenticao o processo de identificao de um usurio (pessoa, processo etc.) em um sistema. Isto feito comparando-se as credenciais passadas pelo usurio com as esperadas pelo sistema. O mtodo mais comum de autenticao o uso de senhas, mas pode-se utilizar vrias outras tcnicas, como biometria. Autorizao o processo de verificao dos direitos que um usurio possui para acessar/manipular um determinado recurso do sistema. Um exemplo seria restringir o acesso de um cliente de um banco a apenas sua prpria conta. Iniciando a autenticao Ao iniciar o processo de autenticao com JAAS, a aplicao deve criar um objeto do tipo javax.security.auth.login.LoginContext, passando para ele um nome de configurao de mdulos de login (que so implementaes da interface javax.security.auth.spi.LoginModule). Essa configurao definida em um arquivo-texto simples, externo aplicao (veja detalhes adiante). O LoginContext responsvel por armazenar as informaes do usurio; o LoginModule, por obter essas informaes. Veja a Listagem 1. Note que, antes de instanciar o LoginContext, foi criado um javax.security.auth.Subject. Um Subject armazena as informaes relacionadas a uma entidade colhidas no processo de autenticao, por exemplo: o nome, o login e a senha de um usurio. Para isso, o Subject usa um ou mais objetos java.security.Principal, representando identidades e, opcionalmente, credenciais pblicas ou privadas.

Listagem 1. Exemplo de autenticao: JMMain.java package jm.jaas; import java.security.*; import javax.security.auth.*; import javax.security.auth.callback.*; import javax.security.auth.login.*; // Usando o JAAS para fazer o login e o logout de um usurio public class JMMain { public static void main(String[] args) { ?// Informaoes e objetos necessrios para o login String nomeConfiguracao = JavaMagazine; Subject subject = new Subject(); CallbackHandler callbackHandler = new JMCallbackHandler(); // Cria LoginContext LoginContext context = null; try { context = new LoginContext( nomeConfiguracao, subject, callbackHandler); }

catch (LoginException le) { ?System.out.println(Erro criando LoginContext. Mensagem: + le.getMessage()); System.exit(1); } // Realiza o login do usurio na aplicao try { context.login(); System.out.println(Login bem sucedido); // Chama o mtodo protegido PrivilegedAction acaoProtegida = new AcaoProtegida(); Subject.doAsPrivileged(subject, acaoProtegida, null); } catch (LoginException le) { System.out.println(Login falhou. Mensagem: + le.getMessage()); } // Realiza o logout do usurio try { context.logout(); } catch (LoginException le) { System.out.println(Logout falhou. Mensagem: + le.getMessage()); ?} } protected static class AcaoProtegida implements PrivilegedAction { public Object run() { // Tenta acessar uma prop. de sistema. Caso no haja uma // PropertyPermission no arquivo de policies indicando que o // Principal pode acess-la, AccessControlException lanada System.getProperty(java.home); System.out.println(Ao protegida executada c/ sucesso.); return null; } } }

O LoginContext tambm espera um objeto do tipo javax.security.auth.callback.CallbackHandler, que relaciona a aplicao com os mdulos de segurana, passando entre eles informaes de autenticao. CallbackHandlers so responsveis, por exemplo, por solicitar ao usurio a digitao de seus dados, ler informaes de um arquivo de propriedades ou obt-las atravs de um smart card, entre outras opes possveis. As principais classes e interfaces do JAAS so apresentadas na Tabela 1. Login, fases e logout Ainda na Listagem 1 note que, aps o LoginContext ser criado, a aplicao chama o mtodo login(). aqui onde se inicia o processo de autenticao, que consiste basicamente de chamar o mtodo login() de cada LoginModule configurado. Toda a dependncia da tecnologia de autenticao est localizada nos LoginModules; eles podem, por exemplo, implementar a lgica pra acessar um

banco de dados e verificar se as informaes passadas pelo usurio conferem. Para que o processo tenha sucesso no obrigatrio que a autenticao em cada mdulo tenha sucesso. Os requisitos e condies para uma autenticao bem sucedida so determinados pela relao entre os mdulos e as propriedades configuradas para eles (veja as opes possveis na Tabela 2). O JAAS usa um esquema de autenticao em duas fases: Primeira fase O mtodo login() de cada LoginModule invocado, retornando true em caso de identificao positiva e false se o mdulo deve ser ignorado. lanada uma LoginException se a autenticao falhar. O processo ocorre na ordem em que os LoginModules so listados na configurao e continua at que todos esses mdulos tenham sido executados, ou at que algum mdulo obrigatrio no autentique o usurio. Segunda fase Nesta fase, dois caminhos podem ser seguidos, dependendo do sucesso da autenticao. Sendo a autenticao bem sucedida, o mtodo commit() de cada LoginModule chamado, montando o Subject com as informaes obtidas no login (note que criado um objeto JMPrincipal representando a identidade autenticada veja a Listagem 4). Caso a autenticao tenha falhado, invocado o mtodo abort() de cada um dos mdulos, para que tenham a oportunidade de destruir qualquer informao armazenada por eles. Finalmente, quando o Subject deixa de ser necessrio, logout() invocado para limpar as informaes armazenadas nele e nos LoginModules. Configuraes de autenticao Para garantir a independncia entre a aplicao e os LoginModules, o JAAS define um arquivo de configurao (com nome padro auth.conf) lido pelo LoginContext na sua inicializao. Nesse arquivo, so especificados os mdulos a serem usados na autenticao, alm de parmetros especficos de cada mdulo. As configuraes podem tambm podem incluir valores default, sob o nome other, que so usadas caso no seja passado um nome de configurao. Caso um LoginContext seja instanciado sem um nome de configurao e no exista uma configurao other, ou se o nome passado no existir, uma LoginException lanada. Veja um esqueleto de um arquivo de configurao de autenticao a seguir: Aplicacao1 { NomeLoginModule1 Flag1 Params1; NomeLoginModule2 Flag2 Params2; }; Aplicacao2 { NomeLoginModule3 Flag3 Params3; }; other { NomeLoginModule4 Flag4 Params4; }; Como se pode ver, a sintaxe bsica de configurao para cada mdulo NomeLoginModule Flag Params. Aqui, NomeLoginModule o nome da classe que implementa o LoginModule, Flag define o papel desse mdulo no processo de autenticao (veja a Tabela 1), e Params uma seqncia opcional de parmetros no formato chave/valor, que so passados em um Map para o LoginModule, no momento da sua inicializao. O auth.conf para nosso exemplo bastante simples: JavaMagazine { jm.jaas.JMLoginModule required;

}; O mtodo mais direto de tornar o arquivo de configurao acessvel para a aplicao informando sua localizao atravs da propriedade de sistema java.security.auth.login.config.

Classe/Interface java.security.Principal javax.security.auth.Subject

javax.security.auth.login.LoginContext

javax.security.auth.spi.LoginModule

javax.security.auth.callback.CallbackHandler

javax.security.auth.callback.Callback

Descrio Representao de uma entidade (um usurio, por exemplo) Conjunto de informaes de identificao e segurana relacionadas a uma entidade, usadas na sua autenticao e autorizao (login e senha, por exemplo) Principal classe do JAAS, responsvel pelo isolamento entre as aplicaes e a implementao de segurana Interface do servio de segurana; em LoginModules que a autenticao realmente ocorre Gancho entre a aplicao e os servios de segurana; usado para colher as informaes necessrias para a autenticao Conjunto de informaes passadas da aplicao para os servios de segurana

Tabela 1. Principais classes e interfaces do JAAS Flag Required Efeito sobre o processo de autenticao A autenticao no LoginModule necessria para o processo de autenticao principal; a autenticao no pra caso a autenticao neste mdulo falhe (ou seja, o sucesso na autenticao deste mdulo necessrio mas no suficiente) A autenticao no LoginModule necessria para o processo de autenticao principal; o processo pra caso a autenticao neste mdulo falhe Autenticao no LoginModule no necessria para o processo de autenticao principal, mas o processo pra caso a autenticao neste mdulo seja bem sucedida A autenticao no LoginModule no necessria para o processo de autenticao principal

Requisite

Sufficient

Optional

Tabela 2. Flags da configurao de LoginModules Listagem 2. Exemplo de LoginModule: JMLoginModule.java package jm.jaas; import java.io.*; import java.util.*; import javax.security.auth.*; import javax.security.auth.callback.*; import javax.security.auth.login.*; import javax.security.auth.spi.*; public class JMLoginModule implements LoginModule { private Subject subject;

private CallbackHandler callbackHandler; private String nome; private char[] senha; // Nome de usuario e senha corretos private final static String NOME = JM; private final static char[] SENHA = {J, a, v, a, M, a, g, a, z, i, n, e}; public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this.subject = subject; this.callbackHandler = callbackHandler; } public boolean login() throws LoginException { // Instancia os callbacks e os passa para o CallbackHandler Callback[] callbacks = new Callback[2]; callbacks[0] = new NameCallback(Digite o nome: ); callbacks[1] = new PasswordCallback( Digite a senha: , false); try { callbackHandler.handle(callbacks); } catch (IOException ioe) { throw new LoginException(ioe.getMessage()); } catch (UnsupportedCallbackException uce) { throw new LoginException(uce.getMessage()); ?} // Compara valores adquiridos com esperados String nome = ( (NameCallback) callbacks[0]).getName(); char[] senha = ((PasswordCallback) callbacks[1]).getPassword(); if (nome.equals(NOME) && Arrays.equals(senha, SENHA)) { this.nome = nome; this.senha = senha; } else throw new LoginException(Nome de usuario ou senha nao conferem); return true; } public boolean commit() throws LoginException { // Carrega informaes da autenticao bem sucedida em // Subject subject.getPrincipals().add(new JMPrincipal(nome)); return true; } public boolean logout() throws LoginException { // Limpa subject subject.getPrincipals().clear(); subject = null; return true; } public boolean abort() throws LoginException { return true; } } Listagem 3. Exemplo de CallBackHandler: JMCallbackHandler.java package jm.jaas;

import java.io.*; import javax.security.auth.callback.*; // CallbackHandler que pede um nome de usurio // e uma senha da linha de comando public class JMCallbackHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, ?UnsupportedCallbackException { // Cria um reader para os dados que virao da linha de // comando // e executa os callbacks que foram passados BufferedReader reader = new BufferedReader( new InputStreamReader(System.in)); for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof NameCallback) { NameCallback nc = (NameCallback) callbacks[i]; System.out.print(nc.getPrompt()); nc.setName(reader.readLine()); } else if (callbacks[i] instanceof PasswordCallback) { PasswordCallback pc = (PasswordCallback) callbacks[i]; System.out.print(pc.getPrompt()); pc.setPassword(reader.readLine().toCharArray()); } else { throw new UnsupportedCallbackException(callbacks[i], Callback inesperado); } } } } Listagem 4. JMPrincipal.java package jm.jaas; import java.security.Principal; public class JMPrincipal implements Principal { private String nome; public JMPrincipal(String nome) { this.nome = nome; } public String getNome() { return nome; } } Listagem 5. jaas.policy grant { permission javax.security.auth.AuthPermission createLoginContext; permission javax.security.auth.AuthPermission modifyPrincipals; permission javax.security.auth.AuthPermission doAsPrivileged; }; grant Principal jm.jaas.JMPrincipal JM { permission java.util.PropertyPermission java.home, read; }; Polticas de segurana

A plataforma Java define um modelo de segurana baseado em um Security Manager. Quando o Security Manager est ativado (o que feito passando a propriedade java.security.manager para a JVM), so usadas permisses de acesso a operaes baseadas num arquivo de polticas de segurana (security policy). Nesse arquivo, podem ser definidos, por exemplo, que o cdigo em determinado diretrio tenha permisso para ler e escrever arquivos. Veja um exemplo de uma dessas permisses: grant CodeBase file:/C:/dir/- { permission java.io.FilePermission arquivo.txt, read,write,delete; }; Aqui definido que arquivo.txt pode ser lido, escrito e apagado apenas por cdigo localizado abaixo de C:/dir. Existem permisses para o uso de arquivos, acesso a propriedades de sistema, conectividade com sockets, operaes de reflection etc. A localizao do arquivo de polticas de segurana definida atravs da propriedade java.security.policy da JVM. Mdulos e Callbacks Um exemplo simples de LoginModule pode ser visto na Listagem 2. Nele solicitado um par nome/senha para o usurio, que depois comparado com valores definidos diretamente no cdigo. Durante o processo de autenticao, primeiro o mtodo initialize() invocado pelo LoginContext (normalmente esse mtodo apenas define referncias para os objetos a serem usados no processo de autenticao). O mtodo login() chamado, e Callbacks so instanciados e passados para o mtodo handle() do CallbackHandler, solicitando as informaes de autenticao ao usurio. O mdulo compara as informaes, que so colhidas atravs dos Callbacks, com os valores esperados e autentica (ou no) o usurio. O CallbackHandler mostrado na Listagem 3 composto apenas por um mtodo handle(), que espera um NameCallback e um PasswordCallback. So solicitadas ao usurio informaes na linha de comando, e estas so depois carregadas nos callbacks correspondentes. Caso algum callback diferente dos esperados seja passado, o mtodo lana uma UnsupportedCallbackException. Autorizao O esquema de autorizao do JAAS baseia-se na chamada de um nico mtodo da classe javax.security.auth.Subject e no Security Manager da plataforma Java, e estende as polticas de segurana de Java, que so baseadas na localizao e assinatura do cdigo (veja o quadro Polticas de segurana). A forma de controlar o acesso a funes e recursos funciona de maneira similar com a diferena que o JAAS baseia-se em Principals em vez de codebases para fazer a autorizao. Para usar autorizao do JAAS, necessrio que o Security Manager da plataforma esteja ativado. Voltando Listagem 1 vemos que, aps a autenticao do usurio, executado o mtodo esttico doAsPrivileged() de Subject. Os parmetros passados so: um Subject, um objeto do tipo java.security.PrivilegedAction representando a ao a ser executada, e um java.security.AccessControlContext (caso seja null, um novo ser criado). Isso invoca o mtodo run() da PrivilegedAction. No exemplo, tenta-se acessar uma propriedade de sistema com o Security Manager do Java ativado, essa operao s ser executada se houver uma permisso de leitura da propriedade correspondente (caso contrrio, uma AccessControlException ser lanada).

Configuraes Uma poltica de segurana definida em arquivos texto com uma sintaxe especial (geralmente com extenso .policy). A sintaxe bsica a seguinte: grant Principal NomeDoPrincipal, Principal ... { ... } Veja um exemplo na Listagem 5. O primeiro grant estabelece permisses para a execuo de aes necessrias para o processo de autenticao e autorizao, por exemplo, a criao de LoginContexts. O segundo mostra um exemplo de poltica baseada em objetos Principal definimos que um Principal de nome JM, da classe JMPrincipal (Listagem 4), pode ler a propriedade de sistema java.home. A localizao desse arquivo definida pela propriedade de sistema java.security.policy. Por fim, aqui est a linha de comando para a chamada da aplicao com todas as propriedades necessrias: java -Djava.security.manager -Djava.security.auth.login.config=auth.conf -Djava.security.policy=jaas.policy jm.jaas.JMMain Concluses O JAAS tem como principal vantagem o total desacoplamento entre as aplicaes e tecnologia de segurana utilizada. O mecanismo de autorizao torna a implementao de segurana bastante simples e pouco intrusiva, e a configurao fica muito flexvel por ser realizada fora da aplicao. java.sun.com/products/jaas Homepage do JAAS java.sun.com/j2se/1.4.2/docs/guide/ security/jaas/JAASRefGuide.html Guia de referncia de JAAS java.sun.com/j2se/1.4.2/docs/guide/security/ PolicyFiles.html Sintaxe dos arquivos de polticas de segurana