Olá, tudo bom? Como vão vocês?
Este artigo é o primeiro de uma série que falaremos sobre segurança em aplicações Java, começando com a primeira parte do artigo sobre Spring Security. Dúvidas e críticas são bem vindas.
Segurança de dados através do Spring Security
A segurança de áreas restritas em aplicações Web escritas em Java não é uma tarefa das mais triviais.
Sabendo que não era simples criar áreas de segurança, em 2003 surge o Acegi Security System for Spring, um framework extremamente configurável e complexo. Comum na época, suas configurações eram baseadas em XML e demorava um tempo para que o desenvolvedor o dominasse completamente.
O projeto Acegi evoluiu e, em 2007, foi incorporado aos projetos do Spring Framework, sendo renomeado para Spring Security.
A versão 2.0 foi lançada em 2008 e em 2010 a versão 3.0, a que iremos utilizar neste artigo.
Download do Framework
Para trabalhar com o Spring Security, você deve realizar o download no endereço http://www.springsource.org/download. No momento em que este artigo é escrito, a versão utilizada é a Spring Security 3.0.2. Clique em Download.
Baixe a versão spring-security-3.0.2.RELEASE.zip. Ao baixar, descompacte o arquivo extraindo todos os JARs existentes no diretório lib.
Também será preciso baixar o Spring Framework. No momento em que este artigo é escrito, a versão utilizada é a Spring Framework 3.0.2.
Como o Spring Security trabalha
Da mesma forma que faríamos se estivéssemos utilizando JAAS, o Spring Security trabalha a segurança através de declarações baseadas em papéis (roles). Seja em XML ou Anotações, o Spring Security não necessita chamar método algum para realizar uma autenticação ou autorização.
Através dos roles definidos, podemos informar ao aplicativo em questão, ao qual está sendo assegurada uma área, quais recursos podem ser acessados ou restringidos a uma determinada pessoa que acessou a área restrita.
Preparando o ambiente de trabalho
Para este artigo, iremos utilizar a IDE da Spring Source, divisão da VMware, criada sobre a plataforma Eclipse, chamada de SpringSource Tools Suite.
Para baixar o SpringSource Tools Suite, clique aqui, preencha o formulário e faça o Download. Como a ferramenta possui uma opção de instalador, use-a como facilitador se desejar. Na própria página onde baixar o arquivo, haverá a explicação da instalação em cada plataforma, em Installation Instructions.
Criando um projeto
No SpringSource Tools Suite, clique no menu File>New>Dynamic Web Project. Na caixa de diálogo New Dynamic Web Project, digite ProjSpringSecurity (ou o nome que desejar) em Project name.
O SpringSource Tools Suite possui embutido um servidor de aplicações Java Web baseado no Apache Tomcat 6, só que com algumas modificações. Entretanto, vamos utilizar o Tomcat, que pode ser adicionado como mostro neste artigo.
Confirme a criação do projeto no botão Finish.
Adicionando as bibliotecas ao Projeto
Com o direito do mouse sobre o projeto, na view Project Explorer, vá até Properties. Na caixa de diálogo das propriedades do projeto, vá até Java EE Module Dependencies. Clique em Add External JARs e adicione os seguintes arquivos:
- org.springframework.aop-3.0.2.RELEASE.jar
- org.springframework.asm-3.0.2.RELEASE.jar
- org.springframework.beans-3.0.2.RELEASE.jar
- org.springframework.context-3.0.2.RELEASE.jar
- org.springframework.core-3.0.2.RELEASE.jar
- org.springframework.expression-3.0.2.RELEASE.jar
- org.springframework.transaction-3.0.2.RELEASE.jar
- org.springframework.web-3.0.2.RELEASE.jar
- spring-security-config-3.0.2.RELEASE.jar
- spring-security-core-3.0.2.RELEASE.jar
- spring-security-taglibs-3.0.2.RELEASE.jar
- spring-security-web-3.0.2.RELEASE.jar
- commons-logging-1.1.1.jar
Note que o 13º item é um JAR que não pertence a família do Spring Framework. Você pode baixar o arquivo compactado, contendo a biblioteca commons-logging-1.1.1.jar, clicando aqui.
Uma aplicação simples com Spring Security
Para exemplificar como funciona o Spring Security, vamos criar uma aplicação simples com apenas uma área segura. Esta área segura será representada dentro de um diretório, chamado admin.
Teremos duas páginas index.jsp: uma na raiz do aplicativo e outra dentro do diretório admin, como mostra a Figura 5.
As páginas JSP
A página index.jsp, existente dentro do diretório admin exibe apenas uma mensagem simples, como mostra a Figura 6, com apenas HTML.
O conteúdo é mostrado na Listagem 1.
Listagem 1 – O conteúdo HTML da página /admin/index.jsp
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Usuário Logado</title> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> </head> <body> <h2>Parabéns, você está logado!</h2> </body> </html>
A página index.jsp encontrada na raiz exibe apenas um link que o leva até a área administrativa. Sua aparência é idêntica a Figura 7.
O conteúdo da página index.jsp encontrada na raiz da aplicação é mostrado na Listagem 2.
Listagem 2 – O conteúdo HTML da página /index.jsp
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Página Inicial</title> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> </head> <body> <h2>Uma aplicação simples com Spring Security</h2> <hr /> <a href="admin">Clique aqui para acessar a área administrativa</a> </body> </html>
Configurando o web.xml
Para que o Spring Security, assim como o Spring, precisamos configurar o web.xml. O Spring Security utiliza um filtro HTTP para interceptar as URLs acessadas e verificar as permissões de acesso.
A Listagem 3 exibe a configuração do arquivo web.xml.
Listagem 3 – O arquivo web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>ProjSpringSecurity</display-name> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
Para configurar o Spring Security, utilizamos o filtro org.springframework.web.filter.DelegatingFilterProxy, devidamente configurado na Listagem 3. O filtro está sendo aplicado em todo o aplicativo, podendo ser visto no elemento <url-pattern />.
Atenção: Um detalhe importante que precisa ser notado é o nome do filtro, colocado no elemento <filter-name/>. Não o altere, pois o Spring já espera pelo nome springSecurityFilterChain.
Configurando o applicationContext.xml
O Spring Security será configurado no arquivo applicationContext.xml. Este arquivo deverá ser criado dentro do diretório WEB-INF, com o conteúdo mostrado na Listagem 4.
Listagem 4 – O arquivo applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"> <http auto-config="true"> <intercept-url pattern="/admin/**" access="ROLE_ADMIN" /> </http> <authentication-manager> <authentication-provider> <user-service> <user name="edson" password="integrator" authorities="ROLE_ADMIN" /> </user-service> </authentication-provider> </authentication-manager> </beans:beans>
No Spring Security, as configurações de autenticação e autorização estão sendo feitas no arquivo de contexto padrão do Spring (applicationContext.xml). Para que este arquivo seja lido, adicionamos no web.xml o elemento <listener />, contendo o listener org.springframework.web.context.ContextLoaderListener.
O listener do Spring faz com que as configurações sejam carregadas na inicialização da aplicação Web.
Ao ser carregado pelo listener, o arquivo da Listagem 4 declara os usuários e suas regras de acesso ao aplicativo.
O controle de acesso é feito pelo elemento <http />, do applicationContext.xml. Este controle é definido no sub-elemento <intercept-url />. O atributo pattern, de <intercept-url />, informa, através de uma expressão, em qual local o filtro deve agir, bem como define a sua regra de acesso, através do atributo access.
Para que possamos definir que qualquer elemento dentro do diretório admin fique acessível somente para os usuários do role ROLE_ADMIN, adicionamos uma expressão comum no Apache Ant.
Caso tenhamos mais de um sub-elemento <intercept-url />, teremos sua interpretação sendo feita por ordem de definição, sendo que, a primeira que atender a regra, será chamada. Na prática, isto significa que, se houver /admin/relatorios/** e /admin/**, o primeiro caso deverá ser lido primeiro, portanto será o primeiro a ser adicionado na ordem em applicationContext.xml.
O atributo auto-config, com o valor true, indica a configuração automática da aplicação para utilizar um formulário de login. O JSP do formulário é gerado automaticamente pelo Spring Security neste caso. A Figura 8 exibe o formulário gerado pelo Spring Security.
Com o atributo <authentication-manager>, gerenciamos os usuários e seus respectivos roles que darão permissão ao diretório especificado anteriormente, em <intercept-url />, pelo filtro.
Para facilitar a compreensão do exemplo, adicionamos apenas um usuário, através de <user/>, informando o nome de usuário, a senha e o seu papel de acesso.
Ao logar no aplicativo, o Spring analisará qual role é permitido no diretório e quem possui tal permissão.
Personalizando o formulário de acesso a área restrita
É interessante ter uma geração automática de formulário no Spring Security, ajuda a testar a codificação, com certeza. Mas não é agradável ao aplicativo como um todo, pois sempre precisamos criar o formulário com as características gerais desenvolvidas no layout das páginas.
Criando a página personalizada de login
Para isso, o Spring Security nos fornece a personalização do formulário. A Listagem 5 exibe o conteúdo da página /login.jsp que ficará na raiz do seu aplicativo, junto com index.jsp.
Listagem 5 – A página login.jsp
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Área Restrita</title> </head> <body> <h2>Área Restrita</h2> <hr /> <% if(request.getParameter("error") != null){ if (request.getParameter("error").equals("invalido")){ %> <p> <span style="color:red"> Usuário ou Senha inválidos </span> </p> <% } //fim do if equals }//fim do if null %> <form action="j_spring_security_check" method="post"> Usuário: <input name="j_username" type="text" value="${not empty login_error ? SPRING_SECURITY_LAST_USERNAME : ''}" /> <br /> Senha: <input type="password" name="j_password"><br /> <input type="submit" value="Efetuar Login"><br /> <a href="index.jsp">Retornar para a Página Inicial</a> </form> </body> </html>
Para que o formulário funcione com o Spring Security, as regras mais básicas são:
- O atributo action deve apontar para j_spring_security_check;
- O atributo name da caixa de entrada de texto, do nome de usuário, deve ser j_username;
- O atributo name da caixa de entrada de senha deve ser j_ password.
Estes princípios básicos farão com que seu formulário funcione com o Spring Security. Entretanto, precisamos mostrar uma mensagem de erro, caso o usuário não tenha colocado as informações necessárias ou, as mesmas não sejam compatíveis com o registrado no sistema para permitir a entrada na área restrita.
É exatamente o papel do if(request.getParameter(“error”) e if (request.getParameter(“error”).equals(“invalido”)), na página login.jsp, personalizado, com um parâmetro que iremos transmitir, através do Spring Security, caso ocorra um erro na permissão.
A página personalizada pode ser vista na Figura 9.
Alterando o arquivo applicationContext.xml
Por fim, mas não menos importante, precisamos alterar o arquivo applicationContext.xml para que o Spring Security passe a trabalhar com a página de login personalizada que criamos. A seguir você tem o trecho, contendo o elemento <form-login/>, que deve ser inserido por entre o elemento <http />:
<form-login login-page=“/login.jsp” authentication-failure-url=“/login.jsp?error=invalido”/>
O elemento <form-login/> é de simples compreensão, pois temos atributos que descrevem bem sua função:
login-page: A página personalizada com o formulário de substituição do padrão existente no framework
authentication-failure-url: URL de retorno caso ocorra um erro. Note que adicionamos, após “?” , error=invalido. Isto demonstra, claramente, que não é uma regra fixa o que pode ser transmitido, caso ocorra um erro, na entrada de uma determinada área restrita.
No próximo artigo sobre Spring Security
Embora tenhamos conhecido os elementos básicos de utilização do Spring Security, restou colocar o acesso ao banco de dados para fazer uma autenticação verdadeira, como ocorre em sistemas.
No próximo artigo veremos como fazer para trabalhar com Spring Security e o acesso ao banco de dados, com um exemplo completo, passo a passo.
Até o próximo artigo pessoALL.