Conhecendo a segurança declarativa do Java (JAAS) – Parte 1
Afinal, o que é esse JAAS ?
O JAAS ou “Java Authentication and Authorization Service” é um conjunto de API’s que visam desacoplar as aplicações dos controles de acesso a recursos da mesma, ficou bonita essa frase hein ? na prática isso significa retirar do desenvolvedor a responsabilidade de ter que controlar o acesso a recursos por perfis de maneira programática( filtros e outros meios ilicitos que eu também já fiz /o\ ). Todo o controle passa a ser feito de maneira declarativa no descritor da aplicação, daí o nome segurança declarativa, intuituivo, não ?
Basicamente o JAAS pode ser atilizado para dois propósitos:
- Autenticação de usuários, ou seja, verificar se o usuário é registrado;
- Autorização de usuários, ou seja, verificar se o usuário já autenticado tem permissão de acesso para determinado recurso protegido;
Tá, mas…o que eu ganho usando o JAAS ?
Muitas coisas, você passa a se preocupar de fato com o código que é importante para a sua aplicação, as restrições a determinados recursos não vão mais interferir na maneira como você desenvolver sua aplicação, você pode por exemplo após ter concluído o desenvolvimento fazer as devidas declarações de quais recursos serão protegidos e quem poderá acessá-los. Implicitamente isso tornará seu código mais legível e focado nas regras de negócio. Sem contar que qualquer modificação nas restrições implicará na mudança de apenas um arquivo(web.xml) e não mais em diversos pontos espalhados pela aplicação.
Tudo muito legal, mas….como eu implemento isso ?
Para demonstrar como implementamos o JAAS vamos sugerir um cenário…
Suponhamos que em sua aplicação você tenha um recurso(neste caso uma JSP…obviamente poderia ser qualquer outra coisa, como servlets, imagens, enfim…) e que você deseje que apenas usuários devidamente autenticados e autorizados possam visualizar essa página.
Para ficar mais fácil a compreensão abaixo esta disposta a estrutura da aplicação onde iremos aplicar os conceitos do JAAS para resolvermos o problema proposto no cenário…
obs.: todos os elementos de relevância serão detalhados na seguência…
Eu chamei a aplicação de “Security”, e nela tenho o meu diretório de conteúdo (WebContent) onde tenho o diretório “WEB-INF”, minha JSP que irá ser mapeada para ser a página de boas vindas(index.jsp) e outro diretório chamado “jsp”. Neste diretório “jsp” temos a “home.jsp” que será a nossa página de acesso restrito e outro diretório chamado “security” onde vamos criar a tela de login(login.jsp) e a tela de erro apresentada caso o login seja falho(error_login.jsp).
Um dos métodos de autenticação de usuário do JAAS consiste em um mecanismo baseado em formulário de autenticação, formalmente conhecido como FORM, que é o método que será abordado neste artigo. Mas a título de conhecimento existem mais três métodos de autenticação que são o DIGEST, o BASIC e o CLIENT-CERT…
Como declaramos qual será o método de autenticação que usaremos ?
No seu deployment descriptor você deverá inserir as seguintes declarações..
<login-config>
<!–INDICA O METODO DE AUTENTICAÇÃO –>
<auth-method>FORM</auth-method>
<form-login-config>
<!–INDICA A JSP DE LOGIN –>
<form-login-page>/jsp/security/login.jsp</form-login-page>
<!–INDICA A PAGINA A SER CAHAMADA CASO O LOGIN SEJA FALHO –>
<form-error-page>/jsp/security/error_login.jsp</form-error-page>
</form-login-config>
</login-config>
Com a declaração acima, estamos dizendo ao container para usar as telas de login,jsp e error_login.jsp para tratar a autenticação, portanto, devemos agora implementar essas JSP’s..
login.jsp
<%@ page language=”java” contentType=”text/html; charset=ISO-8859-1″
pageEncoding=”ISO-8859-1″%>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>
<html>
<head>
<title>LOGIN</title>
</head>
<body>
<form action=”j_security_check” method=”POST”>
username: <input type=”text” name=”j_username” /><br />
password: <input type=”password” name=”j_password” /><br />
<input type=”submit” value=”login” />
</form>
</body>
</html>
IMPORTANTE:
A propriedade action do formulário deve conter o valor “j_security_check”, o campo que receberá o nome do usuário deverá se chamar “j_username” e o campo que receberá a senha deverá se chamar “j_password”. Sim, se você mudar algum desses valores obrigatorios sua autenticação terá dois possíveis caminhos…erro durante a execução ou ninguém nunca se conseguirá autenticação…
error_login.jsp
<%@ page language=”java” contentType=”text/html; charset=ISO-8859-1″
pageEncoding=”ISO-8859-1″%>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>
<html>
<head>
<title>LOGIN</title>
</head>
<body>
<p>Usuário e/ou Senha inválidos !</p>
<a href=”javascript:history.go(-1);”>Tentar Novamente</a>
</body>
</html>
Declarando os “papéis” ou “perfis” de usuário que sua aplicação trabalhará…
No web.xml você deve declarar todas os perfis de usuários ou papéis aos quais os usuários poderão ser atribuidos…no nosso caso vamos criar a role “web_user”
<!– ROLES DE SEGURANÇA –>
<security-role>
<role-name>web_user</role-name>
</security-role>
Implementando a “home.jsp”…
<%@ page language=”java” contentType=”text/html; charset=ISO-8859-1″ pageEncoding=”ISO-8859-1″%>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>
<html>
<head>
<title>HOME</title>
</head>
<body>
Welcome, ${userPrincipal.name} !
</body>
</html>
Restringindo a página “home.jsp” a usuários que possuam o “papel” de “web_user”…
Bom, para restringir o acesso de “algo” usando JAAS devemos seguir o conceito de que esse “algo” é um recurso, então dentro da tag de restrição de segurança nós mapeamos um recurso pela URL e atribuimos um nome a este recurso…nesta deficição podemos também especificar o método HTTP que deve ser tratato…lembrando que a não deficição dos métodos HTTP faz com que ambos GET e POST sejam tratados…
Logo em seguida, estamos definindo quais são os “papéis” que poderam ter acesso ao recurso mapeado…
<!– MAPEAMENTO DA SEGURANÇA –>
<security-constraint>
<web-resource-collection>
<web-resource-name>home</web-resource-name>
<url-pattern>/jsp/home.jsp</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>web_user</role-name>
</auth-constraint>
</security-constraint>
Definindo e implementando a página de boas vindas ou welcome-file da nossa aplicação..
Para definirmos a página que será chamada quando o usuário acessar o “document root” da aplicação nos acrescentamos ao nosso arquivo web.xml o seguinte trecho de código..
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
Segue abaixo a implementação desta página…
index.jsp
<%@ page language=”java” contentType=”text/html; charset=ISO-8859-1″
pageEncoding=”ISO-8859-1″%>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + “://” + request.getServerName() + “:” + request.getServerPort() + path + “/”;
%>
<html>
<head>
<base href=”${basePath}” />
<title>INDEX.JSP</title>
</head>
<body>
<a href=”jsp/home.jsp”>HOME ( recurso protegido )</a>
</body>
</html>
Bom, estamos quase terminando…
falta agora definirmos os usuários e os papéis que cada usuário poderá exercer na aplicação… para isso existem algumas formas de armazenar esses usuários e suas respectias responsabilidades. Esse foi o fator pelo qual separei esse artigo em 2 partes. Neste primeiro momento vamos armazenar essas informações em arquivos de propriedades que ficaram em nosso container, na segunda parte deste artigo nós aprimoraremos um pouco este exemplo fazendo com que as informações sejam armazenadas em um banco de dados.
Definindo os arquivos de propriedades…
Precisaremos crirar dois arquivos de propriedades, o “users.properties” e o “roles.properties”…
o users.properties é o arquivo onde iremos armazenar os usuários e suas respectivas senhas…
já o arquivo roles.properties é onde iremos associar ao usuário os papéis que ele poderá desempenhar na aplicação…
users.properties
root=123
roles.properties
root=web_user
Agora que já temos em mãos os arquivos necessários é só colocarmos esses arquivos no diretório “jboss-X.X.X.GA\server\default\conf“…lembrando que estas configurações são para se trabalhar com o JBoss…cada container tem a sua maneira de implementar essas configurações…
Pronto, agora basta inicializarmos o servidor e via browser tentar acessar nossa aplicação…
a página “index.jsp” será apresentada. Nela haverá um link para o recurso protegido(home.jsp) que quando acionado automaticamente requisitará a autenticação do usuário…Para conseguir acesso utilize “root” e “123” como usuário e senha respectivamente…
Qualquer dúvida ou falha no artigo por favor notifique… =)
Tipo, nao existe nenhuma configuração estilo anotações!?? xml sux a lot!! ^^
Pela especificação, toda a configuração do JAAS é feita pelo descritor da aplicação…porém, existem algumas alternativas “fora do padrão” como o “Security Annotation Framework”(http://safr.sourceforge.net/) ou se você quiser anotações e ainda mais controle sobre a segurança, por exemplo a ponto de dizer que um método só pode ser acessado por um usuário em determinado horário e se ele pertencer a um determinado perfil existem recursos mais evoluídos como JBoss Seam + Jboss Rules…estes sim em breve virarão padrão no Java EE 6…
Estou estudando o assunto…futuramente comentarei algo mais detalhado sobre o assunto aqui no blog =)
Mas eu acredito que a configuração do JAAS via xml, em aplicações de pequeno e médio porte, sejam ideais…
ps: próximo final de semana estarei postando a segunda parte do artigo… XD
kd o artigo sobre JBOSS Seam!? hehe
Eu tenho uma dúvida!
Aparentemente é impossível fazer com que o Adsense logue nas paginas protegidas por esse método. Realmente é isso mesmo? Você já testou? Minhas paginas são todas protegidas assim e vou ter que mudar tudo graças ao Adsense…
Nice! Thanks!
Muito legal esse tipo de autenticação… só tenho uma dúvida…. as senhas no arquivo de configuração… ficam desprotegidas mesmos… quero dizer, não dá pra deixá-las criptografadas ?
Grato.
Very Nice! Thanks!
Nice Site! Thanks!
Muito bom essa explicação, agora como faço pra usar JASS em uma aplicação JSF usando oc4j, agradeço!
Muito bom cara, parabéns, tow testando, vlw!
Opa, publicaçao muito boa, já tem previsão para a “Parte 2″
Paulo,
Executei os passos acima com o maximo de exatidão possivel, porém quando executo o login o processo fica travado no j_security_check. Você sabe porque isso poderia ocorrer?
Grato
Rafael
Estou desenvolvendo uma aplicação com JAAS, com a mesma estrutura do seu projeto de exemplo.
Quando eu informo usuário e senha incorretos, funciona. redirecionando para a mesma página de login. Quando, porém, informo usuário e senha corretos, dá o seguinte erro:
HTTP Status 400 – Invalid direct reference to form login page
O que pode estar acontecendo de errado?
Obrigado.
Flávio
Paulo….
Gostaria de saber se publicou a parte 2 da autenticação com JAAS , pegando os dados no DB???? Estou implementando…..e estudando sobre isso…
Se tiveres, desde já agradeço
Boa noite, Paulo, tenho a seguinte dúvida: Meu site tem um link para cadastro de users, que está na mesma página de login, ou seja, o login no sistema ainda não foi feito. Então, como posso permitir que uma pessoa se cadastre uma vez que não existe um user logado no jaas neste momento?
Obrigado pela atenção.