![]() |
![]() |
![]() |
|
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() |
www.linkcom.com.br | ![]() |
Autenticação e Autorização
A segurança de uma aplicação pode ser dividida em duas partes: autenticação
e autorização.
A autenticação é o processo de identificação do usuário.
Geralmente, através de uma tela onde o usuário fornece seu login e senha.
Autorização é o processo onde o sistema verifica se determinado usuário possui
permissão para acessar alguma funcionalidade do sistema.
O NEO possui suporte apenas para a implementação do processo de autorização,
que é o processo mais complicado.
Uma das formas de se implementar a autorização é utilizando JAAS.
O NEO detecta se algum login foi feito utilizando JAAS, então
nenhum trabalho extra é necessário. Como a configuração via JAAS
muda de servidor para servidor, mostraremos um exemplo 'manual' de autenticação.
Como a autenticação e autorização andam juntas, vamos implementar
as duas ao mesmo tempo.
Para o processo de autorização o NEO necessita que algumas interfaces sejam implementadas,
são elas:
- User: POJO que representa um usuário no sistema
- Role: POJO que representa um papel (ou nível) no sistema
- Permission: POJO que representa a permissão de determinado papel para determinado controller do sistema
- AuthorizationDAO: DAO que fornece métodos para descobrir informações sobre a autorização
Essas interfaces não definem nenhum relacionamento entre User e Role. Esse relacionamento
é definido na aplicação, da forma que o desenvolvedor desejar.
Não é necessário que os POJOs sejam entidades do Hibernate. Mas como nossos dados
estão em um banco de dados, aproveitaremos o bean para fazer o mapeamento no banco de dados.
Um exemplo de implementação para essas interfaces seria o seguinte:
package entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import br.com.linkcom.neo.authorization.User; import br.com.linkcom.neo.bean.annotation.DescriptionProperty; import br.com.linkcom.neo.types.Password; /** * Representa um usuário no sistema */ @Entity public class Usuario implements User { Integer id; String nome; String login; String password; @Id @GeneratedValue public Integer getId() { return id; } //API public String getLogin() { return login; } @DescriptionProperty public String getNome() { return nome; } //API @Password public String getPassword() { return password; } public void setId(Integer id) { this.id = id; } public void setLogin(String login) { this.login = login; } public void setNome(String nome) { this.nome = nome; } public void setPassword(String password) { this.password = password; } } package entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import br.com.linkcom.neo.authorization.Role; import br.com.linkcom.neo.bean.annotation.DescriptionProperty; /** * Representa um papel no sistema, um nível de permissão. * Ex.: Administrador, Usuário, Financeiro */ @Entity public class Papel implements Role { Integer id; String description; String name; @Id @GeneratedValue public Integer getId() { return id; } //API @DescriptionProperty public String getDescription() { return description; } //API public String getName() { return name; } public void setDescription(String description) { this.description = description; } public void setId(Integer id) { this.id = id; } public void setName(String name) { this.name = name; } } package entity; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import br.com.linkcom.neo.authorization.impl.AbstractPermission; /** * Representa a permissão para determinado papel em determinada tela */ @Entity public class Permissao extends AbstractPermission { Integer id; Papel role; String permissionString; String path; @Id @GeneratedValue public Integer getId() { return id; } public String getPath() { return path; } //API public String getPermissionString() { return permissionString; } //API @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="role_id") public Papel getRole() { return role; } public void setId(Integer id) { this.id = id; } public void setPath(String path) { this.path = path; } public void setPermissionString(String permissionString) { this.permissionString = permissionString; } public void setRole(Papel role) { this.role = role; } } package dao; import java.util.List; import java.util.Map; import org.springframework.orm.hibernate3.HibernateTemplate; import entity.Papel; import entity.Permissao; import entity.Usuario; import entity.UsuarioPapel; import br.com.linkcom.neo.authorization.AuthorizationDAO; import br.com.linkcom.neo.authorization.Permission; import br.com.linkcom.neo.authorization.Role; import br.com.linkcom.neo.authorization.User; import br.com.linkcom.neo.persistence.QueryBuilder; /** * DAO de autorização, detectado automaticamente pelo NEO. * Fornece informações sobre autorização para o framework */ public class NeoAuthorizationDAO implements AuthorizationDAO { private HibernateTemplate hibernateTemplate; public void setHibernateTemplate(HibernateTemplate hibernateTemplate) { this.hibernateTemplate = hibernateTemplate; } //API /** * Retorna a lista de todos os papeis do sistema */ public Role[] findAllRoles() { ListNote que foi utilizado um bean extra, UsuarioPapel, para fazer o relacionamento entre user e role. Esse bean é apenas um bean de ligação, para fazer um relacionamento muitos para muitos. package entity; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToOne; /** * Faz o relacionamento entre Usuário e Papel * Relacionamento muitos para muitos entre usuario e papel */ @Entity public class UsuarioPapel { Integer id; Usuario usuario; Papel papel; @Id @GeneratedValue public Integer getId() { return id; } @ManyToOne(fetch=FetchType.LAZY) public Papel getPapel() { return papel; } @ManyToOne(fetch=FetchType.LAZY) public Usuario getUsuario() { return usuario; } public void setId(Integer id) { this.id = id; } public void setPapel(Papel papel) { this.papel = papel; } public void setUsuario(Usuario usuario) { this.usuario = usuario; } }Esses beans são entidades no banco de dados e também representam informações para o processo de autorização. O NEO irá detectar qualquer classe que implemente AuthorizationDAO na aplicação, não coloque @Bean nessa classe. Essa classe pode ficar em qualquer pacote e ter qualquer nome. Essas classes ainda não tem efeito de autorização nenhum na aplicação, uma vez que nenhum controller foi configurado com autorização. Antes de prosseguirmos com a autorização vamos criar o processo de autenticação. Crie na aplicação um novo módulo do NEO. Esse módulo, no exemplo desse tutorial irá se chamar secured. Para criar um módulo do neo é necessário um DispatcherServlet, no nosso caso para a URL /secured/* no web.xml. Criar o diretório /WEB-INF/jsp/secured. E colocar um arquivo base.jsp em /WEB-INF/jsp/secured. Vamos criar um filtro que apenas usuários logados no sistema possam acessar esse módulo. Crie o filtro conforme o modelo: package filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import br.com.linkcom.neo.core.standard.Neo; public class AuthenticationFilter implements Filter { String loginPage = "/modulo/login"; public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if(Neo.getUser() == null){ request.getRequestDispatcher(loginPage) .forward(request, response); } else { chain.doFilter(request, response); } } public void destroy() { } public void init(FilterConfig config) throws ServletException { } }O authenticationFilter irá redirecionar para um controller caso não exista usuário no sistema, o código desse controller é o seguinte: package controller; import org.springframework.web.servlet.ModelAndView; import dao.NeoAuthorizationDAO; import entity.Usuario; import br.com.linkcom.neo.authorization.User; import br.com.linkcom.neo.controller.Controller; import br.com.linkcom.neo.controller.DefaultAction; import br.com.linkcom.neo.controller.MessageType; import br.com.linkcom.neo.controller.MultiActionController; import br.com.linkcom.neo.core.web.WebRequestContext; import br.com.linkcom.neo.view.menu.MenuTag; /** * Controller que fará o login do usuário na aplicação. * Se o login for efetuado com sucesso irá redirecionar para /secured/Index */ @Controller(path="/modulo/login") public class LoginController extends MultiActionController { private static final String AFTER_LOGIN_GO_TO = "/secured/Index"; NeoAuthorizationDAO authorizationDAO; public void setAuthorizationDAO(NeoAuthorizationDAO authorizationDAO) { this.authorizationDAO = authorizationDAO; } /** * Action que envia para a página de login */ @DefaultAction public ModelAndView doPage(WebRequestContext request, Usuario usuario){ return new ModelAndView("login", "usuario", usuario); } /** * Efetua o login do usuário */ public ModelAndView doLogin(WebRequestContext request, Usuario usuario){ String login = usuario.getLogin(); //se foi passado o login na requisição, iremos verificar se o usuário existe e a senha está correta if(login != null){ //buscamos o usuário do banco pelo login User userByLogin = authorizationDAO.findUserByLogin(login); // se o usuário existe e a senha está correta if(userByLogin != null && userByLogin.getPassword().equals(usuario.getPassword())){ //Setando o atributo de seção USER fazemos o login do usuário no sistema. request.setUserAttribute("USER", userByLogin); //Limpamos o cache de permissões o menu. //O menu será refeito levando em consideração as permissões do usuário request.setUserAttribute(MenuTag.MENU_CACHE_MAP, null); return new ModelAndView("redirect:"+AFTER_LOGIN_GO_TO); } //Se o login e/ou a senha não estiverem corretos, avisar o usuário request.addMessage("Login e/ou senha inválidos", MessageType.ERROR); } //limpar o campo senha, e enviar para a tela de login já que o processo falhou usuario.setPassword(null); return doPage(request, usuario); } }e o login.jsp <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="n" uri="neo"%> <%@ taglib prefix="t" uri="template"%> <n:form> <n:bean name="usuario"> <t:propertyConfig renderAs="double" mode="input"> <n:panelGrid columns="2" align="center" style="width: 180px; background-color: #F8F4EA; padding:2px; border: 1px solid #949087" columnStyles="font-size: 12px;"> <n:panel style="background-color:#6699CC; color:white; font-weight:bold" colspan="2"> Login </n:panel> <t:property name="login"/> <t:property name="password" label="Senha"/> <n:submit action="doLogin" panelColspan="2" panelAlign="right">Enviar</n:submit> </n:panelGrid> </t:propertyConfig> </n:bean> </n:form>Após criar as classes devemos registrar dois filtros no web.xml. O filtro de autenticação (o que criamos) e o filtro de autorização (fornecido pelo NEO). <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <!-- Listener que inicializa a aplicação --> <listener> <listener-class>br.com.linkcom.neo.core.web.init.ContextLoaderListener</listener-class> </listener> <!-- Filtro para criar o contexto do NEO --> <filter> <filter-name>neoFilter</filter-name> <filter-class>br.com.linkcom.neo.core.web.NeoFilter</filter-class> </filter> <filter-mapping> <filter-name>neoFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Filtro de autenticação. Verifica se o usuário está logado --> <filter> <filter-name>authenticationFilter</filter-name> <filter-class>filter.AuthenticationFilter</filter-class> </filter> <!-- Esse filtro irá barrar todo acesso anonimo à /secured/* --> <!-- Se desejar barrar acesso anonimo à outras URLs duplique o filter-mapping e altere a url-pattern --> <filter-mapping> <filter-name>authenticationFilter</filter-name> <url-pattern>/secured/*</url-pattern> </filter-mapping> <!-- Filtro de autorização, verifica as permissões para determinado recurso --> <filter> <filter-name>authorizationFilter</filter-name> <filter-class>br.com.linkcom.neo.authorization.AuthorizationFilter</filter-class> </filter> <filter-mapping> <filter-name>authorizationFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Servlet necessário para Ajax --> <servlet> <servlet-name>ajaxServlet</servlet-name> <servlet-class>br.com.linkcom.neo.view.AjaxServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ajaxServlet</servlet-name> <url-pattern>/ajax/*</url-pattern> </servlet-mapping> <!-- Servlet necessário do NEO, provê JS e CSS --> <servlet> <servlet-name>resourceServlet</servlet-name> <servlet-class>br.com.linkcom.neo.view.ResourceServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>resourceServlet</servlet-name> <url-pattern>/resource/*</url-pattern> </servlet-mapping> <!-- Servlet necessário para os inputs select-one-path e select-one-button --> <servlet> <servlet-name>selecionarCadastrarServlet</servlet-name> <servlet-class>br.com.linkcom.neo.view.SelecionarCadastrarServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>selecionarCadastrarServlet</servlet-name> <url-pattern>/SELECIONARCADASTRAR/*</url-pattern> </servlet-mapping> <!-- Módulo da aplicação --> <servlet> <servlet-name>modulo</servlet-name> <servlet-class>br.com.linkcom.neo.controller.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>modulo</servlet-name> <url-pattern>/modulo/*</url-pattern> </servlet-mapping> <!-- Módulo seguro da aplicação, só é possível acessar esse módulo se o usuário tiver logado no sistema --> <servlet> <servlet-name>secured</servlet-name> <servlet-class>br.com.linkcom.neo.controller.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>secured</servlet-name> <url-pattern>/secured/*</url-pattern> </servlet-mapping> </web-app>A ordem dos filtros deve ser seguida. Primeiro vem o neoFilter, depois o authenticationFilter e depois o authorizationFilter. Nesse momento se quisermos acessar qualquer recurso dentro de /secured o authenticationFilter irá interceptar a requisição e enviar o usuário para a tela de login até que o usuário esteja logado no sistema. O LoginController após logar o usuário no sistema faz o redirecionamento para /secured/Index. Mas poderia ser para qualquer outro controller. Lembre-se de implementar um controller para receber a requisição após o login no sistema. |
Últimas postagens
Alguem ainda usa o NEO?
Autor: Nunes
sem hibernate
Autor: csilva2001
Erro ao fazer update [RESOLVIDO]
Autor: Tchaco
Erro CrudController
Autor: edu_fernandes
Artigos, Livros e documentação
Autor: Nunes
Crud Master Detail
Autor: carlos ribeiro
[RESOLVIDO] Problema ao iniciar aplicação com NEO
Autor: R.Albany
gerar relatórios
Autor: mouzer
[RESOLVIDO] Missing required Java project: 'Neo'
Autor: r3n4n
The method ognl(String) in the type NeoFunctions is not applicable for the arguments ()
Autor: r3n4n
Dúvida com videos em flash e jsp
Autor: thiago cassimiro
Criptografar senhas Postgresql
Autor: labavel
Fazer upload da imagem em disco e no banco
Autor: labavel
Estilo no detalhe
Autor: Tchaco
Acessar o equivalente ao Neo.getUser() dentro da JSP
Autor: konkix
Dúvida de iniciante
Autor: Eder
Acesso a banco de dados
Autor: Nunes
Gravar Imagem no Banco
Autor: Tchaco
Campos AUTOCOMPLETE
Autor: vanessa
Assinatura Digital
Autor: biharck
Projeto NEO pode ser utilizado em um grande cliente do grande ABC.
Autor: Nunes
Layout Mestre Detalhe
Autor: viniciusst
Problemas com o type CPFCNPJ
Autor: viniciusst
Combo de Estado
Autor: viniciusst
Suporte a dois SGBD's Simultâneos
Autor: biharck
Many-to-Many
Autor: Tux
Gerando relatórios
Autor: viniciusst
Problemas com filtro listagem
Autor: vberga
Projeto descontinuado
Autor: viniciusst
Crud com erro - MySQL
Autor: viniciusst
Erro de cast no DAO
Autor: biharck
@DescriptionProperty Multiplos
Autor: joaopedro
Geração de tabelas - CRUD
Autor: Nunes
iReport
Autor: jlevi
Impressão de PDF em Bamatech MP20-MI
Autor: Alisson
Retorno - Novidades
Autor: vinicius.janones
CRUD Avançado
Autor: cassioseffrin
CRUD
Autor: miltonmmjr
Upload Multiplo de Imagem
Autor: robmsjr
Problema com anotação
Autor: tulio
Integração com Hibernate
Autor: Nunes
Dúvida quanto à referência a imagens
Autor: mmfalcao
Problema com atributo do tipo byte[]
Autor: tulio
Relacionamento Many to Many
Autor: LeonardoBH
Problema ao subir aplicação de upload de arquivos
Autor: cassioseffrin
Neo versão 3.4.0
Autor: pedro.goncalves
Problemas neo 3.4 + jboss 5 e Cascade no Hibernate
Autor: vberga
Erro ao anotar @Bean
Autor: edson.goncalez
Suporte a paginação
Autor: int80h
Menu vertical
Autor: fabricio.costa
|
Copyright © 2020 www.neoframework.com.br. Projeto sob a licença LGPL. |