You are on page 1of 18

Artigo Java Magazine 22 - Segurana no J2EE

Notebook: Created: URL:


Java Live Segurana no J2EE Parte 1: Desenvolvimento e deployment no Tomcat A prenda a utilizar as facilidades de autenticao e controle de acesso da plataforma J2EE para aplicaes web com o mais popular container web Fernando Lozano Quantas v ezes v oc j construiu um mdulo de segurana para um sistema ou site web? Muda a linguagem de programao, muda a empresa, muda o projeto, mas h sempre a mesma necessidade: v alidar senhas de usurios e permisses de acesso. No univ erso J2EE no preciso reinv entar a roda. A especificao determina como uma aplicao pode definir regras de controle de acesso e como obter informaes sobre o usurio logado. Esta srie, em duas partes bastante independentes, demonstra como configurar e utilizar os recursos de segurana prev istos pelo J2EE para implementar polticas de autenticao e de controle de acesso, incluindo exemplos prticos de implementao nos serv idores liv res mais populares. O Tomcat o foco desta primeira parte e o JBoss, o da parte final. A abordagem ser prtica, pela construo de um exemplo em que cada usurio pode acessar um conjunto diferente de pginas. O exemplo ser depois modificado para ilustrar outros cenrios freqentemente requisitados pelos usurios. Segurana declarativa O J2EE utiliza uma abordagem declarativa para as configuraes de segurana, baseada no conceito de roles (papis). Uma aplicao define um ou mais roles e depois quais operaes podem ser realizadas por cada um desses roles. Grosso modo, um role um grupo de usurios. O conceito de operao depende do contexto: em um container web, consiste no acesso a uma URL; em um container EJB uma operao representa a inv ocao de um mtodo remoto. O cdigo da aplicao no chama nenhum mtodo para v alidar uma senha, nem para autorizar ou no a realizao de uma operao. Fazer isso seria uma abordagem procedural. Pode-se fazer uma analogia com comandos select do SQL e comandos seek do dBase e C lipper. No SQL, o select descrev e quais dados so desejados, mas no quais ndices acessar e arquiv os de dados abrir; no dBase/C lipper arquiv os e ndices so abertos manualmente, e acessos a v rias tabelas se tornam loops aninhados. Comandos select so portanto uma abordagem declarativ a; comandos seek , uma abordagem procedural. claro que nem todas as situaes podem ser tratadas de forma declarativ a. Por isso as A PIs de Serv lets e de EJB definem mtodos para descobrir quem o usurio corrente (ou se no foi ainda feito o login) e se este usurio possui ou no um role especfico. Com esses mtodos, possv el tratar no cdigo da aplicao qualquer situao que no possa ser tratada pelos descritores. Vrios exemplos sero apresentados ao longo do artigo. Roles e operaes so parte da estrutura da aplicao, por isso so definidas pelo desenv olv edor e especificadas no descritor (com URIs mapeadas para serv lets) ou na interface dos EJBs. Por outro lado, a especificao J2EE no define como as senhas so v alidadas, nem como um usurio associado a um role. Essas questes so responsabilidade do administrador do serv idor de aplicaes, e cada produto tem total liberdade de implement-las da forma que for julgado mais conv eniente. Assim sendo, qualquer aplicao que utilize os recursos padro do J2EE para autenticao e controle de acesso ir exigir um deploy ment (instalao) customizado para o serv idor de aplicaes adotado. A lguns desenv olv edores v em isto como desv antagem, preferindo implementar seus prprios esquemas de autenticao e controle de acesso v isando garantir que suas aplicaes possam ser instaladas de forma fcil e inalterada em qualquer serv idor do mercado. O problema que acabam reinv entando a roda e na maioria das v ezes ficando com a segurana deficiente, por falta de conhecimento especializado no assunto.

Eng. de Software 29/12/2010 19:50 http://www.devmedia.com.br/post-10128-Artigo-Java-Magazine-22-Seguranca-no-J2EE.html

Controle de acesso em aplicaes web


A Listagem 1 demonstra a sintaxe para a declarao de roles e regras de controle de acesso para uma aplicao web de exemplo, que est disponv el para download no site da Jav a Magazine. Note que so definidos dois roles usuario e administrador e que a pgina inicial da aplicao tem acesso pblico, pois sua URL (/index.jsp ) no se enquadra nos padres url-pattern definidos para nenhum dos elementos webresource-collection presentes no descritor.

Se no for definida uma regra de controle de acesso para uma operao, esta operao poder ser realizada livremente por usurios noautenticados. Caso se deseje que todas as pginas de uma aplicao web estejam sob controle de acesso, deve-se inserir todas elas em um mesmo diretrio, e definir um padro como nome_da_pasta/*, correspondendo a todas as pginas da aplicao. No se deve definir simplesmente /*, padro que corresponde a todas as pginas da aplicao. Isso porque caso sua aplicao utilize uma pgina de login customizada, esta pgina deve estar acessvel para usurios annimos, assim como a pgina de erro associada.
Observ e que, da forma como as regras de controle de acesso foram definidas, os conjuntos de pginas acessv eis para usurios e administradores so completamente separados. C aso se deseje que o administrador tambm possa acessar as pginas dos usurios, h trs alternativ as:

Acrescentar mais um role-name com o v alor administrador dentro do auth-constraint do elemento web-resource-collection

Pginas do Usurio Acrescentar mais um url-pattern com o v alor /usuarios/* dentro do auth-constraint do web-resource-collection Pginas do

A dministrador Dar aos usurios que recebem o role administrador tambm a role usuario

Agora v eja na Figura 1 a estrutura do pacote war da aplicao de exemplo. O contedo das pginas liv re, pois estamos interessados apenas em v erificar quais usurios conseguem acessar quais pginas. A pgina index.jsp contm link s para as pginas de ndice em cada subdiretrio, funcionando como um menu de acesso aplicao. Por simplicidade o exemplo consiste apenas de pginas JSP, mas as mesmas regras se aplicam a serv lets, pois cada serv let mapeado para uma ou mais URIs no descritor web.xml. A restrio de acesso baseada em URIs tambm se aplica a pginas estticas, criando uma estrutura simples e uniforme para controlar o acesso a todas as pginas da aplicao. por isso que alguns serv idores de aplicaes, como o Tomcat, desabilitam em suas configuraes padro o acesso a serv lets pelo nome da classe (com a URI /serv lets/pacote.nomeDaC lasse), apesar desse tipo de acesso ser prev isto pela especificao de Serv lets. O acesso pelo nome de classe permitiria que um serv let sujeito a controle de acesso pela sua URI (mapeada explicitamente no web.xml) fosse acessado por usurios no-autorizados, pois seria utilizada uma URI diferente.

Listagem 1. Descritor web.xml para a aplicao de exemplo


<?xml v ersion="1.0" encoding="UTF-8"?> <web-app xmlns="http://jav a.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jav a.sun.com/xml/ns/j2ee http://jav a.sun.com/xml/ns/j2ee/web-app_2_4.xsd" v ersion="2.4">

<!-- ... mapeamentos de serv lets e parmetros de inicializao -->

<security -constraint> <web-resource-collection> <web-resource-name>Paginas do Usuario </web-resource-name> <url-pattern>/usuarios/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>usuario</role-name> </auth-constraint> </security -constraint> <security -constraint> <web-resource-collection> <web-resource-name>Paginas do Administrador</web-resource-name> <url-pattern>/admin/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>administrador</role-name> </auth-constraint> </security -constraint> <security -role> <role-name>usuario</role-name> </security -role> <security -role> <role-name>administrador</role-name> </security -role> <!-- ... aqui entra a configurao de login da aplicao --> </web-app>

Figura 1. Estrutura de pginas da aplicao de exemplo


A utenticao em aplicaes web
Tendo definido as regras de controle de acesso, devem ser estabelecidas as regras de autenticao. A especificao de Serv lets define quatro formas possv eis de se configurar o login, trs delas gerenciadas pelo serv idor web 1 e definidas pelo protocolo HTTP, e uma gerenciada pelo prprio container web. So elas: 1. 2. 3. 4. HTTP Basic A uthentication HTTP Digest Authentication HTTPS Client A uthentication Form Based A uthentication

Nas duas primeiras formas de autenticao o nav egador exibe uma janela de login, sendo fornecidas as credenciais do usurio por meio de cabealhos HTTP. Na terceira, dev e ser instalado um certificado digital no nav egador do usurio, semelhante ao instalado em um serv idor web para uso de HTTPS; a simples presena deste certificado autentica o usurio. Na quarta forma de autenticao, uma pgina definida pela aplicao pede o login e senha do usurio Os desenv olv edores em geral preferem a quarta forma de autenticao (Form Based), pois enquanto que nas duas primeiras ele no tem controle sobre a aparncia da tela de login, na terceira opo necessrio configurar as mquinas dos usurios uma a uma, o que no v iv el exceto em pequenas intranets. Vamos apresentar neste momento a autenticao Basic; depois passaremos para a autenticao Form. Os seguintes elementos dev em ser acrescentados ao descritor web.xml para configurar esta forma de autenticao: <login-config> <auth-method>BASIC</auth-method> <rea lm -na m e >Ex em plo de Segura na J2EE</rea lm -na m e> </login-config>

O elemento realm-name identifica o domnio (ou zona) de segurana para o nav egador web. Assim o nav egador sabe se pode ser utilizada uma senha j informada antes pelo usurio, ou se dev e ser requisitada uma nov a senha. O texto fornecido neste elemento ser apresentado pelo nav egador em sua janela de login, como mostra a Figura 2 . Sob o ponto de v ista do desenv olv edor, a aplicao de exemplo estaria pronta para ser executada. Mas o administrador do serv idor ainda tem que configurar um container web para autenticar usurios e reconhecer os roles definidos pela aplicao.

Figura 2. Janela de autenticao do Mozilla ao acessar o link Pginas dos usurios da aplicao de exemplo
Validao de senhas no T omcat Dev e ser configurado um realm2 para que o Tomcat seja capaz de v alidar senhas e associar roles a usurios. Diferentes tipos de realms obtm as informaes sobre senhas e roles de diferentes fontes de dados, que podem ser arquiv os XML, bancos de dados relacionais (v ia JDBC) ou diretrios LDAP (v ia JNDI). Voc pode, claro, estender o Tomcat com nov os realms produtos de terceiros utilizam esta capacidade para permitir a integrao com os bancos de dados de usurios do Unix, Windows e Netware.

Um realm pode ser definido em qualquer nv el da hierarquia de elementos do arquiv o server.xml do Tomcat, e se aplica a todas as aplicaes (contextos) dentro daquele nv el. Assim, pode-se ter desde um nico banco de dados de usurios para todos os domnios v irtuais hospedados pelo mesmo serv idor, at bancos de dados isolados para cada contexto de cada domnio; ou qualquer configurao entre esses dois extremos. Veja a seguir as alteraes feitas no arquiv o server.xml para v alidar senhas utilizando um arquiv o chamado users.xml (mostrado na Listagem 2 ): <Realm className= "org.apache.catalina.realm.Memory Realm" pathname="conf/users.xml" />

Assumindo uma instalao padro do Tomcat 5, insira este elemento imediatamente antes de <Host name=localhost...> e comente qualquer outro elemento <Realm> presente no server.xml. Os roles admin e manager definidos no users.xml, assim como o usurio admin, esto presentes para que seja possv el executar as aplicaes padro do Tomcat, Manager e A dmin. Leitores interessados em mais detalhes sobre as aplicaes administrativ as do prprio Tomcat podem consultar o artigo desta coluna na Edio 19. J podemos copiar o arquiv o war da aplicao de exemplo para a pasta webapps do Tomcat e acessar a URL http://127.0.0.1:8080/jm-

seguranca-j2ee. Ao serem clicados os link s Pginas dos usurios ou Pginas dos administradores o nav egador ir pedir por um login e senha,
exibindo uma janela semelhante Figura 3 . Para os usurios/roles definidos como exemplo, caso seja fornecido o login fernando com senha jav a, apenas o link de usurios ser aceito; com o login lozano senha tomcat, apenas o segundo poder ser acessado. Se um usurio tentar acessar uma pgina que no esteja autorizado a acessar, ser exibida uma pgina de erro gerada pelo container (v eja a Figura 4) .

Listagem 2. Arquivo users.xml, que fornece logins, senhas e roles para o realm configurado
<?xml v ersion='1.0' encoding='utf-8'?> <tomcat-users> <role rolename="administrador"/> <role rolename="usuario"/> <role rolename="manager"/> <role rolename="admin"/> <user username="admin" password="admin" roles="manager,admin"/> <user username="fernando" password="jav a" roles="usuario"/> <user username="lozano" password="tomcat" roles="administrador"/> </tomcat-users>

Figura 3. Pgina inicial e pgina do usurio da aplicao de exemplo

Figura 4. Pgina de erro quando o usurio no tem permisso de ver a pgina


Como fazer logoff?
Retornando Figura 3 , note que no existe um link de logout. Isto proposital, v isto que o protocolo HTTP no define esta operao. A nica forma de se deslogar o usurio, segundo o padro HTTP, fechar todas as janelas do nav egador. Este problema decorre de o protocolo HTTP ser stateless (sem memria/estado). Pelo protocolo, o nav egador poderia pedir a digitao da senha nov amente para cada pgina, mas por comodidade pede apenas a primeira v ez que encontra um nov o realm. A senha digitada guardada em memria no nav egador e reenv iada sempre que o serv idor web indicar uma pgina que necessita de autenticao. O serv idor sempre ir indicar que uma pgina restrita necessita de autenticao, mesmo que o usurio tenha acabado de nav egar por outra pgina do mesmo realm. Em suma, no existe no protocolo HTTP o conceito de login do usurio. Na v erdade, mesmo o conceito de sesso HTTP que utilizamos na programao de serv lets e pginas JSP inexistente no protocolo HTTP. A sesso simulada pelo container web, sem que o serv idor web tenha conhecimento disto, portanto no adianta inv alidar a sesso para forar um logout, como feito na autenticao baseada em formulrios, que v eremos mais adiante.

O leitor poder encontrar na internet exemplos de como fazer logout ou mudar o usurio em aplicaes web, utilizando as formas de autenticao previstas pelo protocolo HTTP, mas qualquer uma delas ir funcionar apenas com uma combinao especfica de navegador e servidor web. Ou ento ir exigir o controle efetivo da autenticao por meio de cookies, variveis de sesso ou outro mecanismo que dependa de cdigo de aplicao. Melhor ento utilizar a autenticao Form Based, entregando este trabalho ao container. Utilizando senhas criptografadas
O arquiv o users.xml, que fornece as senhas e roles para cada usurios no ltimo exemplo, contm as senhas em texto simples, sem criptografia. No recomendado, por questes de segurana e priv acidade dos usurios, que senhas estejam armazenadas em um lugar onde um inv asor ou mesmo o prprio administrador de sistema possa recuper-las. Felizmente todas as opes de realm fornecidas com o Tomcat possuem o atributo digester , que permite especificar um dos algoritmos de criptografia de mo-nica pela classe java.security.MessageDigest do JCE para criptografar a senha fornecida pelo usurio. A senha fornecida pelo usurio criptografada pelo container e comparada com a senha armazenada em forma criptografada pelo realm. Modifique ento o arquiv o server.xml conforme o trecho a seguir: <Realm className="org.apache.catalina.realm.Memory Realm" pa thnam e="conf/users.x m l" digester=MD5 /> Agora necessrio gerar as senhas criptografadas e armazen-las no users.xml. No seria difcil escrev er uma aplicao utilizando as classes do JC E para ler uma senha do teclado e fornecer sua forma criptografada (v eja o artigo de Bruno Souza nesta edio), mas o Tomcat j fornece tal utilitrio pronto para uso. necessrio acrescentar os pacotes bin/jmx.jar , bin/commong-loggin-api.jar e server/lib/catalina.jar ao classpath e ento executar a classe org.apache.catalina.realm.RealmBase. A seguir, um exemplo de uso deste utilitrio para criptografar a senha atribuda ao usurio fernando: > java org.apache.catalina.realm.RealmBase -a MD5 java jav a:93f725a07423fe1c889f448b33d21f46

A primeira linha a linha de comando; na opo -a indicado o algoritmo a ser utilizado (no caso, MD5); o argumento jav a a senha. A sada do programa uma linha de texto, fornecendo a senha original e a senha criptografada separados por um sinal de dois-pontos. A senha dev e ser ento copiada para o arquiv o users.xml, que fica semelhante Listagem 3 . Reinicie o Tomcat e v erifique se as senhas ainda so reconhecidas. importante ressaltar aqui que foram criptografadas apenas as senhas armazenadas no arquiv o users.xml (ou no banco de dados, ou diretrio LDAP, se forem adotadas outras opes de realms do Tomcat). A senha ainda est sujeita a captura em trnsito, pois no mecanismo HTTP Basic ela transmitida em texto puro (no-criptografado) para o serv idor web. Veja o quadro At onde a criptografia garante segurana? para uma discusso sobre como formas de ev itar esta v ulnerabilidade.

Listagem 3. Modificaes no arquivo users.xml para utilizar senhas criptografadas

<user username="admin" password="21232f297a57a5a743894a0e4a801fc3" roles="manager,admin"/> <user username="fernando" password="93f725a07423fe1c889f448b33d21f46b" roles="usuario"/> <user username="lozano" password="1b359d8753858b55befa0441067aaed3" roles="administrador"/

Validando senhas contra um banco de dados


O uso de um arquiv o XML no a opo mais adequada para um serv idor em produo. Embora seja possv el substituir a classe MemoryRealm utilizada no exemplo pela classe UserDatabaseRealm, que permite a criao e alterao de usurios, senhas e roles sem reiniciar o serv idor, manter todos os dados em memria em geral no ser eficiente. Isso fora o fato de que informaes de login e senha so freqentemente compartilhadas com outros aplicativ os. Uma opo mais interessante, usar o JDBCRealm ou DataSourceRealm, que obtm estas informaes de um banco de dados relacional. A diferena entre as duas classes que a primeira faz a conexo ao banco da forma tradicional (com DriverManager.getConnection() ), e a segunda utiliza um DataSource JNDI, da mesma forma que se recomenda fazer em aplicaes J2EE. O Tomcat fornece ainda o JNDIRealm, que permite utilizar um serv idor LDA P como fonte das informaes de autenticao. Antes de criar o realm, dev emos criar tabelas de usurios e roles, com o formato dado pela Listagem 4 , e depois inserir nestas tabelas alguns registros de usurios, conforme a Listagem 5 . Observ e que estamos utilizando senhas pr-criptografadas pelo algoritmo MD5, conforme v isto no tpico anterior.

As tabelas poderiam ser bem diferentes, pois os atributos do JDBCRealm permitem definir os nomes e campos das tabelas. Poderia haver campos adicionais de interesse da aplicao, como o nome e o e-mail do usurio.
O Tomcat 5 j fornece as classes do banco de dados embutido HSQLDB, que utilizado por alguns dos seus exemplos. Vamos aprov eitar esta facilidade para definir o banco de dados de usurios: 1. Acrescente as classes do HSQLDB ao classpath; elas esto em common/lib/hsqldb.jar , dentro da instalao do Tomcat. No Linux,

execute o comando: $ export CLASSPATH=$CLASSPA TH:$TOMCAT_HOME/common/lib/hsqldb.jar E no Windows: > set C LA SSPATH=%CLASSPA TH%;%$TOMC AT_HOME%\common\lib\hsqldb.jar

2.

Inicie o serv idor, onde /bd/users o nome do banco de dados, que ser criado automaticamente:

jav a org.hsqldb.Serv er -database /db/users

3.

Execute os scripts de criao das tabelas e dos usurios/roles de teste (digitando os comandos em uma linha):

> jav a org.hsqldb.util.ScriptTool -url jdbc:hsqldb:hsql: -database //127.0.0.1 -script tabelas.sql

> jav a org.hsqldb.util.ScriptTool -url jdbc:hsqldb:hsql: -database //127.0.0.1 -script usuarios.sql

4.

Verifique se as tabelas esto mesmo criadas e preenchidas, utilizando o Database Manager do HSQLDB (para isso, execute um comando

como select * from users): > jav a org.hsqldb.util.DatabaseManager -url jdbc:hsqldb:hsql://127.0.0.1 Com o banco de dados de usurios e roles preparado, modifique a definio do realm conforme a Listagem 6 . Lembre-se de remov er (ou comentar) a definio do realm criada anteriormente. Reinicie o Tomcat e teste o acesso s pginas da aplicao de exemplo. Tudo dev e funcionar como antes, mas utilizando o banco de dados em v ez do arquiv o users.xml. Experimente tambm alterar a senha do usurio no banco de dados, ou os seus roles associados; v erifique que a mudana reconhecida imediatamente. Observ e ainda que a mudana na autenticao, de um arquiv o XML para um banco relacional, no exigiu modificaes na aplicao nem em seu descritor web.xml. A s alteraes foram realizadas apenas no server.xml do Tomcat.

Listagem 4. Tabelas de usurios e roles para o Tomcat (tabelas.sql)


create table users ( login v archar(15) not null primary k ey , passwd v archar(32) not null ); create table roles ( login v archar(15) not null, role v archar(15) not null,

primary k ey (login, role) );

Listagem 5. Inserindo no banco os registros correspondentes aos usurios admin, fernando e lozano (usuarios.sql)
insert into users v alues ('admin', '21232f297a57a5a743894a0e4a801fc3'); insert into roles v alues ('admin', 'admin'); insert into roles v alues ('admin', 'manager'); insert into users v alues ('fernando', '93f725a07423fe1c889f448b33d21f46b'); insert into roles v alues ('fernando', 'usuario'); insert into users v alues ('lozano', '1b359d8753858b55befa0441067aaed3'); insert into roles v alues ('lozano', 'administrador');

Listagem 6. Modificaes no server.xml para utilizar o JDBCRealm e o banco de dados HSQLDB


<Realm className="org.apache.catalina.realm.JDBC Realm" driv erName="org.hsqldb.jdbcDriv er" connectionURL="jdbc:hsqldb:hsql://127.0.0.1" connectionName="sa" connectionPassword="" digest="MD5" userTable="users" userNameC ol="login" userCredC ol="passwd" userRoleTable="roles" roleNameCol="role" /> Pginas de erro customizadas A pgina de erro de acesso negado pode ser customizada da mesma forma, como qualquer outra pgina de erro, utilizando os recursos prev istos na especificao do HTTP. Um exemplo de pgina de erro customizada est na Listagem 7 . Ela permite ao usurio ser informado do erro e retornar ao menu do sistema. Note o uso do mtodo getContextPath() para gerar a URL de retorno ao ndice da aplicao. Link s relativ os costumam no funcionar em pginas de erro, pois a URL v ista pelo nav egador no a da pgina de erros em si, mas a da que prov ocou o erro. Ou seja, v oc nunca sabe qual o diretrio corrente de uma pgina de erro para construir link s relativ os corretos. Para ativ ar a pgina de erro customizada, acrescente ao descritor web.xml os seguintes elementos: <error-page> <error-code>403</error-code> <location>/erro403.jsp</location> </error-page> Depois recarregue a aplicao por meio do Manager do Tomcat. Tente nov amente acessar uma pgina a qual o perfil do usurio no fornece acesso (por exemplo, pginas administrativ as com o usurio fernando). O resultado ser como na Figura 5 . Os cdigos de erro so os cdigos padronizados do protocolo HTTP; 403 corresponde ao erro de acesso negado. Consulte a especificao do protocolo HTTP para os outros cdigos de erro definidos (v eja link s). Note que a pgina de erro foi colocada no diretrio raiz do contexto, para que no seja inclusa em um dos web-resource-collections que exigem autenticao. Caso contrrio, a prpria pgina de erro poderia gerar um erro de login inv lido ou de acesso negado.

Listagem 7. Pgina de erro customizada para erros de acesso negado (erro403.jsp)


<%@ page isErrorPage="true" %> <html> <body > <h1>Demo de Segurana J2EE<hr></h1> <p> Voc no tem acesso pgina: <br> <%= request.getRequestURL() %> <p> <a href="<%= request.getC ontextPath() %>">Voltar...</a> </body > </html>

Figura 5. Pgina de erros customizada, conforme vista pelo usurio


Pginas de login customizadas O mecanismo de autenticao HTTP Basic acaba sendo pouco utilizado em sistemas de informao e portais dev ido s suas limitaes. Mas til quando se quer que uma aplicao web seja acessada por outra aplicao em v ez de por um usurio humano. o caso, por exemplo, da aplicao Manager do Tomcat. Espera-se que suas pginas de deploy ment e recarga de aplicaes web sejam acessadas diretamente por buildfiles Ant e outros tipos de scripts, para automatizar a instalao e atualizao de aplicaes. O mecanismo preferido pelo desenv olv edor Jav a, para uso geral, a Form Based Authentication, autenticao baseada em formulrios. O descritor web.xml da aplicao especifica uma pgina de login que ser exibida automaticamente pelo container web, sempre que o usurio tentar nav egar para uma pgina que exija autenticao. O usurio ento fornece o login e senha, que so v alidados pelo container; e o nav egador redirecionado para a pgina requisitada originalmente. As informaes do usurio corrente so armazenadas em atributos reserv ados3 na sesso HTTP, de modo que inv alidar a sesso causa o logoff do usurio. importante notar que a pgina de login nunca dev e ser chamada diretamente pela aplicao. Dev e-se deixar que o container o faa. Caso seja desejada uma pgina de login explcita, uma possibilidade criar uma pgina (ou serv let) que apenas redireciona o usurio de v olta para a pgina principal da aplicao, mas esta pgina est contida em um web-resource-collection que exige autenticao. A Listagem 8 mostra as alteraes no web.xml para configurar a autenticao baseada em formulrios para a aplicao. Ela substitui, claro, a configurao mostrada para a autenticao Basic. Dev em ser fornecidas uma pgina de login e uma pgina de erro de login. A pgina de erro no em nada diferente de uma pgina comum (ao contrrio das pginas de erro que so associadas a excees Jav a ou erros HTTP no web.xml). Mas a pgina de login dev e seguir algumas regras: 1. 2. Os campos que recebem a digitao do login e da senha dev em ser chamados, respectiv amente j_username e j_password O action do formulrio dev e ser a URL j_security _check

A URL j_security_check tambm no deve ser invocada explicitamente pela aplicao.


Temos na Listagem 9 um exemplo de pgina de login, e na Listagem 10 uma pgina de erro. As duas so apresentadas na Figura 6 . Nos fontes disponv eis para download temos a aplicao jm-seguranca-j2ee-form, contendo o descritor modificado e as pginas de login e de erro. A ssim o leitor pode experimentar tanto com a autenticao gerenciada pelo serv idor web quanto com a gerenciada pelo container web. Observ e que a pgina de login salv a a sua URL no atributo de sesso pagina. Isto serv e para que a pgina de erro de login possa gerar o link de Tentar nov amente, pois o container no passa nenhuma informao sobre o recurso que se tentou acessar, nem fornece a opo de tentar nov amente caso o login ou a senha no sejam reconhecidos.

Listagem 8. Modificaes no web.xml para autenticao baseada em formulrios


<login-config> <auth-method>FORM</auth-method> <form-login-config> <form-login-page>/login.jsp</form-login-page> <form-error-page>/loginInv alido.jsp</form-error-page> </form-login-config> </login-config>

Listagem 9. Pgina de login do exemplo (login.jsp)


<html> <body > <% request.getSession().setAttribute("pagina", request.getRequestURL()); %> <h1>Demo de Segurana J2EE<hr></h1> <p>

Esta pgina s pode ser acessada por usurios autenticados <form method="post" action="j_security _check "> <table> <tr><td>Login:</td> <td><input size=15 name="j_username"> </tr> <tr><td>Senha:</td> <td><input ty pe="password" size=15 name="j_password"> </tr> <tr><td colpsan="2"><input ty pe="submit" v alue=" Ok "> </tr> </table> </form> </body > </html>

Listagem 10. Pgina de erro de login (loginInvalido.jsp)


<html> <body > <h1>Demo de Segurana J2EE (Form)<hr></h1> <p> Login ou senha incorretos. <p> <a href="<%= request.getSession().getAttribute("pagina") %>">Tentar nov amente...</a> <p> <a href="<%= request.getC ontextPath() %>">Voltar...</a> </body ></html>

Figura 6. Pginas de autenticao e de erro de login


A gora sim, fazendo o logoff
Como as informaes sobre o usurio autenticado so salv as pelo container na sesso, basta inv alid-la para fazer o logoff. A Listagem 11 ilustra como poderia ser uma pgina de logoff, e a pgina principal do segundo exemplo (disponv el para download) inclui um link que a chama. Como na configurao padro do Tomcat (e de qualquer outro container web) sesses HTTP expiram aps alguns minutos de inativ idade (o tempo configurv el no descritor web.xml da aplicao), um usurio que, por exemplo, se ausente do seu computador sem sair da aplicao ser deslogado automaticamente. Alm disso, o cook ie utilizado para manter a sesso HTTP no lado do nav egador criado de modo a no ser preserv ado entre uma inv ocao e

outra do nav egador. Portanto aps fechar o nav egador ser necessrio fazer um nov o login. Entretanto, o usurio permanece autenticado, tanto no mtodo Basic quando no mtodo Form, se ele sair da aplicao para v isitar outro site. Dessa forma ainda h margem para um usurio espertinho utilizar o login de outro usurio sem que ele o perceba. Nada substitui o treinamento dos usurios quando o assunto segurana. Exceto pela forma de se fazer o logoff, tudo o que foi v isto antes sobre autenticao HTTP Basic se aplica igualmente autenticao baseada em formulrios. A configurao do container web no afetada pelo mecanismo de autenticao da aplicao, assim as mesmas definies de realms do Tomcat e o uso de criptografia podem ser utilizados com os dois exemplos.

Listagem 11. Pgina de logoff da aplicao (logoff.jsp)


<% request.getSession().inv alidate(); %> <html><body > <h1>Demo de Segurana J2EE (Form)<hr></h1><p> Sesso encerrada <p> <a href="./">Voltar...</a> </body ></html>

Single Sign-on Na configurao padro do Tomcat, cada aplicao web (ou contexto) mantm suas informaes de autenticao em separado, mesmo que todos os contextos utilizem um mesmo realm. Isso significa que se existirem v rias aplicaes web hospedadas no mesmo serv idor o usurio precisar fornecer nov amente o login e senha a cada v ez que mudar de aplicao. Tendo em v ista que a maioria das empresas organiza suas intranets como um conjunto de aplicaes web independentes, mas fazendo parte do mesmo portal, o usurio espera ter que digitar seu login e senha uma nica v ez, na primeira pgina restrita que for acessada (ou na primeira pgina v isitada na intranet). Para obter este efeito no Tomcat, dev e ser configurada no nv el do host a "v lv ula" (valve)4 de Single Sign-on (login nico). O seguinte exemplo ilustra a sintaxe deste elemento: <Valv e className= "org.apache.catalina.authenticator.SingleSignOn" /> Porm tome cuidado com a mistura de aplicaes que utilizam autenticao Basic e aplicaes que utilizam autenticao Form, pois as credenciais do usurio sero remov idas do container, mas no do nav egador web. Voc pode v erificar o efeito nos dois exemplos construdos neste artigo. Primeiro modifique o server.xml e reinicie o Tomcat; depois entre na aplicao jm-seguranca-j2ee-form (o segundo exemplo) e fornea as credenciais do usurio fernando. Entre na aplicao jm-seguranca-j2ee (primeiro exemplo) e depois na rea dos usurios. Veja que no ser pedida nenhuma informao de autenticao. Agora retorne para a aplicao jm-seguranca-j2ee-form. Faa o logoff e entre na pgina de usurios apenas para confirmar que a aplicao pede nov amente o login a senha; mas em v ez de clicar no boto "Ok " da pgina de login, retorne para o primeiro exemplo. Observ e que ele no ir pedir a senha para acessar as reas restritas. A recomendao portanto utilizar apenas aplicaes com autenticao baseada em formulrios no mesmo host do Tomcat. Isto ev ita o risco de um usurio achar que fez o logoff, enquanto que para o nav egador o login ainda esteja v lido. Quem o usurio corrente? A A PI de Serv lets fornece trs mtodos, caso a aplicao necessite tomar alguma deciso baseada em qual usurio esteja logado, todos da classe HttpServletRequest: ? getRemoteUser() retorna o nome do usurio fornecido na requisio HTTP, de modo que ele s relev ante se for utilizado algum

mecanismo de autenticao gerenciado pelo serv idor web. C aso seja utilizada autenticao baseada em formulrios, este mtodo sempre retornar null. ? getUserPrincipal() retorna um objeto da classe java.security.Principal, que encapsula o usurio autenticado pelo container. Este

mtodo funciona com qualquer mecanismo de autenticao. ? isUserInRole() informa se o usurio correntemente autenticado est ou no associado ao role cujo nome passado como argumento.

Veja que no so fornecidos mtodos para listar os usurios existentes, nem para listar os roles aos quais o usurio est associado. Mesmo assim, os dois ltimos so suficientes para qualquer situao que se apresentar. O getRemoteUser() dev e ser ev itado, j que ele no se aplica autenticao baseada em formulrios, mas pode ser substitudo em qualquer situao pelo segundo mtodo, getUserPrincipal() .

Pgina de login obrigatria


A aplicao jm-seguranca-j2ee-proc , tambm inclusa nos fontes para download, exemplifica algumas caractersticas desejadas por muitos desenv olv edores para suas aplicaes. Ela tem uma pgina inicial apresentada na Listagem 12 , que comea fornecendo um nico link : Entrar no sistema. Clicar neste link prov oca a autenticao do usurio, fazendo a aplicao retornar para a mesma pgina inicial, mas agora com link s para as operaes que ele pode realizar no sistema.

Lgica condicional como scriptlets em pginas JSP tendem rapidamente a ficar de difcil leitura, como na Listagem 12 . Considere nestes casos

utilizar a JSTL.
A pgina autentica.jsp simples; ela apenas redireciona o nav egador de volta para a pgina de ndice: <% // neste ponto a autenticao j foi feita pelo container response.sendRedirect(request.getContextPath()); %> Para que a aplicao funcione como desejado, dev e ser acrescentada uma nov a regra de controle de acesso ao descritor web.xml, apresentada na Listagem 13 . A Figura 7 ilustra como o login nesta aplicao funciona sob o ponto de v ista do usurio. O nome * para um role indica que qualquer role aceito, ou seja, que as URLs relacionadas podem ser acessadas por qualquer usurio autenticado. No definir uma regra de controle de acesso significa que usurios annimos podem acessar a pgina sem fornecer nenhuma senha. As outras regras de controle de acesso dev em ser mantidas; caso contrrio ser fcil burlar a segurana da aplicao. Qual a v antagem de se utilizar a segurana declarativ a neste caso, onde o usurio obrigado a passar por uma pgina de login antes de poder ter acesso a qualquer outra pgina da aplicao? A principal v antagem v em do fato que o usurio no pode pular a pgina de login fornecendo diretamente uma URL. Se no fosse utilizada a segurana declarativ a do J2EE, seria necessrio inserir em cada pgina um teste para v erificar se o usurio j fez o login, ou configurar um filtro (java.servlet.Filter ) para fazer essa v erificao em todas as pginas. Outra v antagem que o usurio pode salv ar nos "favoritos" do seu nav egador a URL para uma pgina qualquer, e o container automaticamente exibir a pgina de login, poupando ao usurio alguns cliques adicionais at chegar a pgina desejada.

Listagem 12. Pgina de ndice (index.jsp) do terceiro exemplo, jm-seguranca-j2ee-proc , ilustrando o uso dos mtodos para segurana procedural na API de Servlets
<html><body > <h1>Demo de Segurana J2EE (Procedural)<hr></h1> <% if (request.getUserPrincipal() == null) { %> <p> <a href="autentica.jsp">Entrar no Sistema</a> <% } else { %> <p> Bem-v indo, usurio <%= request.getUserPrincipal().getName() %> <% if (request.isUserInRole("usuario")) { %> <p> <a href="usuarios/">Pginas dos usurios</a> <% } if (request.isUserInRole("administrador")) { %> <p> <a href="admin/">Pginas dos administradores</a> <% } %> <p> <a href="logoff.jsp">Logoff</a> <% } %> </body ></html>

Listagem 13. Modificaes no descritor web.xml para que um acesso a pgina autentica.jsp provoque a exibio da pgina de login
<security -constraint> <web-resource-collection> <web-resource-name>Fora a Atenticao</web-resource-name>

<url-pattern>/autentica.jsp</url-pattern> </web-resource-collection> <auth-constraint> <role-name>*</role-name> </auth-constraint> </security -constraint>

Figura 7. Usurio se logando na aplicao jm-seguranca-j2ee-proc, exemplificando um usurio administrador e um no-administrador


Formulrio de login na pgina inicial
Outra situao corriqueira em aplicaes web o caso de pginas que exibem informaes para usurios annimos, deixando em um canto da tela um formulrio para login, depois do qual so exibidas informaes adicionais. J v imos que a pgina de login dev e ser mostrada pelo container; assim nossa pgina inicial seria incompatv el com a segurana declarativ a do J2EE. Ou no? Um pouco de criativ idade e um pequeno trecho de cdigo Jav aScript resolv em a aparente incompatibilidade. Primeiro fazemos com que o

formulrio na pgina inicial (Listagem 14 ) utilize como seu action uma pgina restrita (no caso autentica.jsp , a mesma do exemplo anterior). Os campos do formulrio de login estaro disponv eis para a pgina de login do container (pois ela parte da mesma requisio HTTP). Esta pgina contm cdigo Jav aScript no ev ento onLoad do corpo da pgina (body) para prov ocar a submisso imediata do formulrio (Listagem 15 ). Note que os campos obrigatrios foram definidos como campos escondidos (hidden). A Figura 8 ilustra a nav egao de um usurio pelo quarto exemplo, jm-seguranca-j2ee-box. Observ e a caixa na parte direita das pginas, que pode ou exibir um formulrio de login ou o nome do usurio autenticado.

Listagem 14. Pgina incial (index.jsp) do quarto exemplo, jm-seguranca-j2ee-box


<html><body > <h1>Demo de Segurana J2EE (Box)<hr></h1> <table border=1> <tr><td> Aqui entrariam as informaes pblicas da aplicao. <% if (request.isUserInRole("usuario")) { %> <p> <a href="usuarios/">Pginas dos usurios</a> <% } if (request.isUserInRole("administrador")) { %> <p> <a href="admin/">Pginas dos administradores</a> <% } %> </td> <td> <% if (request.getUserPrincipal() == null) { %> <form method="post" action="autentica.jsp"> <table> <tr><td>Login:</td> <td><input size=15 name="login"> </tr> <tr><td>Senha:</td> <td><input ty pe="password" size=15 name="senha"> </tr> <tr><td colpsan="2"><input ty pe="submit" v alue=" Ok "> </tr> </table> </form> <% } else { %> Usurio: <%= request.getUserPrincipal().getName() %> <p> <a href="logoff.jsp">Logoff</a> <% } %> </td></tr> </table> </body ></html>

Listagem 15. Pgina de login (login.jsp) do quarto exemplo


<html> <body onLoad="document.forms[0].submit()">

<% request.getSession().setAttribute("pagina", request.getRequestURL()); %> <h1>Demo de Segurana J2EE (Box)<hr></h1> <p> Autenticando usurio... <form method="post" action="j_security _check "> <input ty pe="hidden" name="j_username" v alue="<%= request.getParameter("login") %>"> <input ty pe="hidden" name="j_password" v alue="<%= request.getParameter("senha") %>"> </form> </body ></html>

Figura 8. Login no quarto exemplo, jm-seguranca-j2ee-box


Segurana e regras de negcio
Daqui em diante, outras necessidades relativ as segurana de uma aplicao web em Jav a (falando em autenticao e controle de acesso) so na v erdade relacionadas com as regras de negcios da aplicao por exemplo, se um usurio pode ou no ver os registros criados por outros usurios no banco de dados. Seria questo de incluir na pesquisa uma condio sobre o login do usurio (obtido v ia getUserPrincipal() ). Outro exemplo seria quando um registro pode ser modificado apenas quando o seu status em aberto, mas no pode ser modificado nem remov ido depois de mudar para o estado fechado. Nenhum mecanismo automatizado ser capaz de decidir que usurio tem acesso a quais dados, ou qual operao pode ser realizada sobre um registro em particular, mas controlar o acesso s pginas da aplicao j mais do que meio caminho andado. Concluses Vimos neste artigo como criar uma aplicao web utilizando os mecanismos de autenticao e controle de acesso definidos pela plataforma J2EE, mais especificamente pelas APIs de Serv lets e JSP. Vimos tambm como aplicar esses mecanismos a alguns cenrios de aplicaes e como configurar o Tomcat para fornecer estes recursos v ia um arquiv o texto ou um banco de dados. Mas ainda no esgotamos o tema. No mostramos, por exemplo, como utilizar SSL para garantir que as senhas de login no sejam capturadas em trnsito, nem como utilizar certificados de cliente (HTPS C lient Authentication). Na prxima edio v eremos como configurar os recursos de autenticao e controle de acesso web dentro do serv idor liv re JBoss, e tambm como utilizar os recursos de segurana da plataforma J2EE para Enterprise Jav aBeans. ____________________________________________ [1]- O Tomcat um serv idor J2EE, significando que implementa funcionalidades prev istas pela especificao J2EE, em especial a funcionalidade de container web. J o conector HTTP do Tomcat implementa a funcionalidade de serv idor web, que poderia ser desempenhada por um serv idor externo como o Apache. (Outros componentes do Tomcat implementam outras caractersticas do J2EE como Datasources JDBC ou serv io de nomes JNI.) [2]- Observ e que realms do Tomcat no tm relao com realms do protocolo HTTP [3]- A especificao de Serv lets define que atributos de sesso cujos nomes iniciem por jav a so de uso interno do container e no dev em

nunca serem consultados ou modificados pela aplicao. Tambm espera-se que uma aplicao no use este prefixo nos seus nomes de atributos; [4]- Valve um componente do Tomcat configurado para atuar como filtro em requisies http recebidas pelo container. O seu uso mais comum salv ar informaes sobre a requisio em logs de acesso ou de erros, mas poderia ser feita qualquer modificao sobre a requisio ou sobre sua resposta.

A t onde a criptografia garante a segurana? O a tributo digest dos rea lm s do Tom cat rea liza a criptografia das se nha s arm a zena das no servidor; e le no afe ta as senhas digita das no nave gador e transm itidas pela requisi o HTTP a t o se rvido r. Se for utilizado o m e ca nism o Ba sic, um sniffe r de rede conse guiria m ostrar a senha digitada pe lo usurio. Ainda assim importante criptografar a senha, no pela segurana da aplicao, mas pela priv acidade dos usurios. Em geral as pessoas utilizam a mesma senha (ou um pequeno conjunto de senhas) tanto dentro quanto fora da empresa. Ningum gostaria de saber, claro, que seria possv el ao administrador da rede ou DBA v er sua senha na aplicao web e utiliz-la para acessar seu e-mail, internet bank ing ou outra aplicao. Utilizar o mecanismo HTTP Digest em v ez de HTTP Basic melhora um pouco a situao, mas nem tanto. Com o mecanismo HTTP Digest, a senha criptografada no nav egador antes do env io para o serv idor. Infelizmente muitos nav egadores no suportam esse mecanismo, e a especificao J2EE no exige que ele seja suportado. Mesmo se v oc utilizar um par nav egador/serv idor web que suporte o HTTP Digest, ainda assim a senha criptografada poder ser capturada em trnsito e posteriormente retransmitida, sendo aceita pelo serv idor, de modo que no hav er necessidade de descriptograf-la. Isso chamado de ataque de replay , pois a repetio de parte do contedo de um pacote suficiente para o inv asor. (Note que esta descrio foi uma grande simplificao do mecanismo e de seus riscos.) Para o leitor preocupado com os riscos que suas senhas correm em intranets e na internet, saiba que as mesmas v ulnerabilidades esto presentes na grande maioria das aplicaes de rede, sejam sistemas de compartilhamento de arquiv os NFS, Windows ou Netware, serv idores de e-mail ou bancos de dados. sabido que segurana no uma questo absoluta (seguro ou no-seguro); algo relativ o. Um sistema pode ser mais ou menos seguro do que o outro, mas todos sero em algum grau inseguros. Uma soluo mais forte dev e utilizar algum mecanismo de autenticao distribuda construdo para ev itar estes riscos, como o Kerberos. Infelizmente o padro HTTP no define nenhuma maneira de utilizar o Kerberos ou similares como mecanismo de autenticao. Outra soluo o uso do protocolo SSL (https://), pelo menos para a pgina de login, pois ele no sujeito a ataques de replay . Vrios sistemas utilizam cdigo Jav aScript no nav egador para criptografar a senha antes da sua transmisso. Neste caso a autenticao feita pelo cdigo da aplicao, no pelo serv idor ou container web. Estes sistemas sofrem dos mesmos riscos que o HTTP Digest (em geral sofrem mais riscos, pois o Digest ao menos tenta ev itar os ataques mais simples de replay ). Portanto complicam a aplicao sem realmente aumentar o nv el de segurana. O risco de se ter uma senha capturada por sniffing (captura de pacotes) na prtica relativ amente baixo. A captura teria que ser feita na rede local do usurio (o que dificultado pelo uso crescente de switches Ethernet), nos roteadores das empresas e prov edores de acesso, ou nos prprios serv idores, significando que j houv e um ataque bem-sucedido, ou que h um funcionrio mal-intencionado em alguma das empresas env olv idas a sua, a empresa do usurio remoto, ou um dos prov edores de acesso e de back bone. O risco bem maior no caso de v rus que instalam monitores de teclado, pginas que imitam aplicaes de home bank ing ou de comrcio eletrnico, usurios que escolhem senhas fceis (o inv asor adv inha as senhas, em v ez captur-las) e usurios que aceitam facilmente tcnicas de engenharia social, dizendo suas senhas ao telefone para qualquer um que afirme ser, por exemplo, um diretor ou tcnico de suporte da empresa.

Links

onjava.com/pub/a/onjava/2002/06/12/form.html
Sobre o mecanismo de autenticao Form definido na especificao de Serv lets

ietf.org/rfc/rfc2068.txt
RFC do IETF que descrev e o protocolo HTTP e seus mecanismos de autenticao

ietf.org/rfc/rfc2069.txt
RFC do IETF que descrev e o mecanismo de autenticao Digest do HTTP

jcp.org/en/jsr/detail?id=154
Especificao de Serv lets, onde so definidos os elementos de autenticao e controle de acesso no web.xml

jak arta.apache.org/tomcat/tomcat-5.0-doc/realm-howto.html
Documentao sobre realms do Tomcat 5

Fernando Lozano (fernando@lozano.eti.br, www.lozano.eti.br ) consultor independente, atuando h mais de dez anos em projetos de integrao de redes, desenv olv imento de sistemas e tuning de bancos de dados. tambm um antigo ativ ista do software liv re, conselheiro do

Linux Professional Institute do Brasil e autor do liv ro "Jav a em GNU/Linux".