Quando se fala em sistemas online, logo deve-se pensar em como tratar a parte da segurança dos dados, de acesso... nessa postagens vamos trabalhar com a segurança de acesso ao sistema, ou seja, o login.
Para fazer esse controle de login vou utilizar o framework Spring Security na versão 3.0.5, estarei disponibilizando os jar's usados, pois não aconselho baixar do próprio site deles, andei fazendo uns testes e o que está disponível agora nessa mesma versão não bate com o que eu baixei a um tempo atrás, então para fazer este projeto o mesmo pode ser baixado por aqui.
O Spring Security trata a autenticação de usuários da seguinte forma: o bloqueio de acesso pode ser feito a diretórios ou a arquivos, ou seja o usuário deve ter a permissão de acesso para o determinado diretório ou arquivo, simplificando... suponhamos que eu tenha um diretório admin, com o Spring Security eu posso definir que apenas usuários que tenham permissão de administrador possa ter acesso ao conteúdo desse diretório. Existem duas formas de fazer a autenticação de acesso, com usuários pré-definidos no xml de configuração ou fazendo a validação de usuário em um banco de dados. Nessa postagem vamos tratar essas duas formas.
Inicialmente vamos criar o nosso projeto de base que vai funcionar para os exemplos com ou sem banco de dados.
Estrutura
Obs: veja que temos um diretório admin e dentro dele um xhtml com o nome de index, então nesse projeto temos 2 index, o da raiz poderá ser acessado sem fazer login, já o que se encontra dentro da do diretório precisará de permissão para ser acessado. Vamos começar com a codificação:
/index.xhtml
/negado.xhtml
/falha.xhtml
/admin/index.xhtml
Depois de criar as páginas para fazer nosso teste, vamos colocar as bibliotecas no projeto, você pode criar uma biblioteca no Netbeans (Ferramentas/Bibliotecas/Nova biblioteca...), ou adicionar diretamente os jar's ao projeto (no projeto, botão direito em Bibliotecas e em add jar).
Os jar's são:
Se você executar ele neste ponto, dará erro, pois com essa configuração ele exige que você tenha um /WEB-INF/applicationContext.xml, então para começar crie um arquivo xml com o nome de applicationContext dentro do WEB-INF...
Segurança de acesso com usuários pré-definidos (sem BD)
Toda a configuração a partir de agora é feita dentro do arquivo applicationContext.xml citado acima.
Abaixo vou postar como ele fica e depois explico as tags:
http: caso não tenha percebido, nesse projeto nós não fizemos uma página de login, isso porque ao setar a propriedade auto-config como true, o próprio Spring Security cria uma página de login (ao final da postagem ensino como personalizar sua página de login), e a propriedade access-denied-page se refere à pagina que deve ser mostrada quando um usuário for logado mas não tem acesso a um diretório ou arquivo (esse arquivo negado.jsf se refere à nossa página criada lá na estrutura do projeto).
intercept-url: esta tag é a responsável por definir quais as permissões que o usuário deve ter para acessar determinados diretórios ou arquivos, no exemplo veja que estamos definindo que o usuário deve ter a permissão ROLE_ADMIN para ter acesso aos arquivos do diretório admin.
logout: esta tag é a responsável por chamar a servlet que desloga o usuário, a propriedade logout-sucess-url se refere a página pra onde o usuário deve ser enviado ao ser deslogado, e o logout-url seria o nome da servlet... lembra que na página /admin/index.jsf nós temos "../logout", pois bem, é a esta configuração que ele está se referindo.
authentication-manager: gerencia a autenticação.
authentication-provider: provedor de autenticação.
user-service: é onde deve-se definir os usuários.
user: é o usuário propriamente dito, a propriedade name é o login do usuário, password é a senha e authorities são as permissões do usuário. Um usuário pode ter mais de uma permissão, estas devem ser separadas por vírgula na propriedade authorities, ficando por exemplo assim:
authorities="ROLE_ADMIN,ROLE_USER".
Bom, assim nosso login com usuário pré-definido já está funcionando, basta testar...
Segurança de acesso autenticando o usuário no banco de dados (com BD)
Para este exemplo vamos utilizar o MySQL, precisamos ter uma tabela com a seguinte estrutura:
Para fazer este projeto, aconselho apenas fazer uma cópia do projeto acima, pois só precisaremos alterar o applicationContext.xml, o mesmo deve ficar assim (logo abaixo do código vou explicar as novas tags):
bean: entre várias possibilidades de utilização desta, nesse exemplo estamos usando ela para definir o dataSource que fará a conexão com o banco de dados MySQL, a propriedade id é nome que identifica esse bean... já a propriedade class se refere a classe do Spring Security que é utilizada para fazer a conexão.
property: serve para setar uma propriedade, neste exemplo é usada para setar propriedades diferentes referentes a conexão ao banco de dados. Vamos ver as propriedades pelos name...
url: é a url de acesso ao banco de dados, 5tads é a database que eu estou usando
driverClassName: é o nome do driver do MySQL
username: é o usuário de acesso ao banco de dados
password: é a senha de acesso ao banco de dados.
Página de login
Como já falei anteriormente, o Spring Security já tem sua página de login que é chamada pela servlet : /spring_security_login ... A página é a seguinte:
Vou criar a minha página de login... dentro de páginas web crie uma nova página JSF, com o nome de login.xhtml, ela será a responsável por substituir a página do Spring Security, o código dela é o seguinte:
Mas vamos entender algumas coisinhas.. como já falei, precisamos usar o form e o input do próprio HTML, outras coisas são de extrema importância para o funcionamento, a action do form precisa ser a servlet j_spring_security_check, assim como os id's dos campos precisam ser j_username e j_passsword ... se eu não me engano quando usa-se o Spring Security de forma personalizada (daria uma longa postagem) tem como usar outros id's, mas não é o nosso foco hoje.
Agora temos que informar ao applicationContext.xml que temos uma página de login, para isso, dentro da tag http, basta informar a seguinte linha:
Pra quem precisar de algo mais complexo como um login personalizado, deixo a seguinte referencia: Spring Security 3 - MVC Integration: Using A Custom Authentication Manager me ajudou muito quando precisei implementar um assim!
O Spring Security trata a autenticação de usuários da seguinte forma: o bloqueio de acesso pode ser feito a diretórios ou a arquivos, ou seja o usuário deve ter a permissão de acesso para o determinado diretório ou arquivo, simplificando... suponhamos que eu tenha um diretório admin, com o Spring Security eu posso definir que apenas usuários que tenham permissão de administrador possa ter acesso ao conteúdo desse diretório. Existem duas formas de fazer a autenticação de acesso, com usuários pré-definidos no xml de configuração ou fazendo a validação de usuário em um banco de dados. Nessa postagem vamos tratar essas duas formas.
Inicialmente vamos criar o nosso projeto de base que vai funcionar para os exemplos com ou sem banco de dados.
Estrutura
/index.xhtml
<h:body>
Usuario não precisa estar logado...
</h:body>
/negado.xhtml
<h:body>
Você não tem permissão de acessar este diretorio.
<a href="index.jsf">Voltar </a>
</h:body>
/falha.xhtml
<h:body>
Login ou senha incorretos...
<a href="index.jsf">Voltar</a>
</h:body>
/admin/index.xhtml
<h:body>
Usuario logado com sucesso!
<a href="../logout">Sair</a>
</h:body>
O /logout eu vou explicar mais pra frente... é coisa da config do Spring Security.Depois de criar as páginas para fazer nosso teste, vamos colocar as bibliotecas no projeto, você pode criar uma biblioteca no Netbeans (Ferramentas/Bibliotecas/Nova biblioteca...), ou adicionar diretamente os jar's ao projeto (no projeto, botão direito em Bibliotecas e em add jar).
Os jar's são:
Outra coisa em comum nos exemplos que vamos fazer é a configuração do Spring Security no WEB-INF/web.xml, dentro dele adicione a seguinte configuração (pode ser logo abaixo da tag web-app):
<!-- Spring security -->
<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>
<!-- Fim spring security -->
Se você executar ele neste ponto, dará erro, pois com essa configuração ele exige que você tenha um /WEB-INF/applicationContext.xml, então para começar crie um arquivo xml com o nome de applicationContext dentro do WEB-INF...
Segurança de acesso com usuários pré-definidos (sem BD)
Toda a configuração a partir de agora é feita dentro do arquivo applicationContext.xml citado acima.
Abaixo vou postar como ele fica e depois explico as tags:
<?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" access-denied-page="/negado.jsf">
<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
<logout invalidate-session="true" logout-success-url="/index.jsf" logout-url="/logout"/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="adm" password="123" authorities="ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
beans: é a raiz do nosso xml, nela é definido os namespace do Spring Security.http: caso não tenha percebido, nesse projeto nós não fizemos uma página de login, isso porque ao setar a propriedade auto-config como true, o próprio Spring Security cria uma página de login (ao final da postagem ensino como personalizar sua página de login), e a propriedade access-denied-page se refere à pagina que deve ser mostrada quando um usuário for logado mas não tem acesso a um diretório ou arquivo (esse arquivo negado.jsf se refere à nossa página criada lá na estrutura do projeto).
intercept-url: esta tag é a responsável por definir quais as permissões que o usuário deve ter para acessar determinados diretórios ou arquivos, no exemplo veja que estamos definindo que o usuário deve ter a permissão ROLE_ADMIN para ter acesso aos arquivos do diretório admin.
logout: esta tag é a responsável por chamar a servlet que desloga o usuário, a propriedade logout-sucess-url se refere a página pra onde o usuário deve ser enviado ao ser deslogado, e o logout-url seria o nome da servlet... lembra que na página /admin/index.jsf nós temos "../logout", pois bem, é a esta configuração que ele está se referindo.
authentication-manager: gerencia a autenticação.
authentication-provider: provedor de autenticação.
user-service: é onde deve-se definir os usuários.
user: é o usuário propriamente dito, a propriedade name é o login do usuário, password é a senha e authorities são as permissões do usuário. Um usuário pode ter mais de uma permissão, estas devem ser separadas por vírgula na propriedade authorities, ficando por exemplo assim:
authorities="ROLE_ADMIN,ROLE_USER".
Bom, assim nosso login com usuário pré-definido já está funcionando, basta testar...
Segurança de acesso autenticando o usuário no banco de dados (com BD)
Para este exemplo vamos utilizar o MySQL, precisamos ter uma tabela com a seguinte estrutura:
<?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" access-denied-page="/negado.jsf">
<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
<logout invalidate-session="true" logout-success-url="/index.jsf" logout-url="/logout"/>
</http>
<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<beans:property name="url" value="jdbc:mysql://localhost:3306/5tads" />
<beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
<beans:property name="username" value="root" />
<beans:property name="password" value="admin" />
</beans:bean>
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT username, password, 'true' as enable FROM users WHERE username=?"
authorities-by-username-query="SELECT username, authority FROM users WHERE username=?"
/>
</authentication-provider>
</authentication-manager>
</beans:beans>
Algumas tags são padrão tanto para usar com ou sem banco, por exemplo a http. Agora vamos ver quais as tags que temos de diferente do exemplo anterior (sem BD).bean: entre várias possibilidades de utilização desta, nesse exemplo estamos usando ela para definir o dataSource que fará a conexão com o banco de dados MySQL, a propriedade id é nome que identifica esse bean... já a propriedade class se refere a classe do Spring Security que é utilizada para fazer a conexão.
property: serve para setar uma propriedade, neste exemplo é usada para setar propriedades diferentes referentes a conexão ao banco de dados. Vamos ver as propriedades pelos name...
url: é a url de acesso ao banco de dados, 5tads é a database que eu estou usando
driverClassName: é o nome do driver do MySQL
username: é o usuário de acesso ao banco de dados
password: é a senha de acesso ao banco de dados.
Veja que o nosso authentication-provider mudou... vamos ver o que ele mudou:
Quando utilizamos o banco de dados para fazer a validação dos usuários, não temos o porque de definir os usuários manualmente no xml, por isso o nosso user-service foi substituído por jdbc-user-service.
jdbc-user-service: a propriedade data-source-ref utiliza como referencia o nosso bean de conexão acima com o id de dataSource, já a users-by-username-query é a query responsável por selecionar o usuário pelo username... quanto ao "'true' as enable" na query, seria por exemplo uma coluna booleana na nossa tabela users dizendo se o usuário está ativo ou não. A outra propriedade é a authorities-by-username-query que tem uma query que é responsável por pegar as permissões do usuário pelo username.
Feito isso... o nosso controle de login com BD está pronto, e é só testar!
Página de login
Como já falei anteriormente, o Spring Security já tem sua página de login que é chamada pela servlet : /spring_security_login ... A página é a seguinte:
<h:body>
<a href="index.jsf">Retornar para a Página Inicial</a>
<form action="j_spring_security_check" method="post">
<h:panelGrid columns="2">
<h:outputText value="Usuario" />
<h:inputText id="j_username" />
<h:outputText value="Senha" />
<h:inputSecret id="j_password" />
</h:panelGrid>
<input type="submit" value="Efetuar Login" />
</form>
</h:body>
Mas agora você deve estar se perguntando... porque não usar o form do próprio JSF e o commandButton no lugar do input? Então, pelos testes que eu fiz, não é possível usar o form e o commandButton do JSF, ele acaba não funcionando direito, e olha que não foi por falta de testes...Mas vamos entender algumas coisinhas.. como já falei, precisamos usar o form e o input do próprio HTML, outras coisas são de extrema importância para o funcionamento, a action do form precisa ser a servlet j_spring_security_check, assim como os id's dos campos precisam ser j_username e j_passsword ... se eu não me engano quando usa-se o Spring Security de forma personalizada (daria uma longa postagem) tem como usar outros id's, mas não é o nosso foco hoje.
Agora temos que informar ao applicationContext.xml que temos uma página de login, para isso, dentro da tag http, basta informar a seguinte linha:
<form-login login-page="/login.jsf" authentication-failure-url="/falha.jsf"/>A propriedade login-page é a responsável por dizer qual é a nossa página de login, e a authentication-failure-url é a página que informa que o login e a senha estão incorretos (fizemos essa página lá no inicio da postagem).
Pra quem precisar de algo mais complexo como um login personalizado, deixo a seguinte referencia: Spring Security 3 - MVC Integration: Using A Custom Authentication Manager me ajudou muito quando precisei implementar um assim!
Referências:



