Laboratório PROGRAMAÇÃO WEB II: Prática 7
Ferramentas utilizadas:
•
NetBeans;
Desenvolvendo a área administrativa da aplicação web
Passo 1: Na pasta Páginas Web crie uma pasta com nome admin, para isso
selecione a pasta e com botão direito do mouse clique em Novo
Pasta.
Clique em Finalizar para concluir.
Passo 3: Na pasta admin, iremos criar o arquivo principal.xhtml, essa página
ficará responsável por apresentar a listagem de usuários cadastrados no
sistema. Observe no código que estaremos utilizando um elemento novo que é
o DataTable, esse elemento do JSF permite a construção de tabelas. Lembre-se
que a extensão do novo arquivo é xhtml, conforme a figura abaixo.
Código principal.xhtml
<?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:f="http://xmlns.jcp.org/jsf/core"> <h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Cadastro de Usuários</title>
</h:head> <h:body>
<h1>Cadastro de Usuários</h1> <h:form>
<h:messages />
<h:dataTable value="#{usuarioBean.lista}" var="usuario" rules="rows" cellpadding="5">
<f:facet name="caption">
A listagem a seguir exibe a relação de todos os usuários do sistema. Você poderá realizar ativação e desativação, edição e exclusão para os usuários.
</f:facet>
<h:column> <h:commandLink action="#{usuarioBean.ativar}"> <h:graphicImage library="imagens" name="usuario_ativo_#{usuario.ativo}.png" style="border:0" /> <f:setPropertyActionListener target="#{usuarioBean.usuario}" value="#{usuario}" /> </h:commandLink> </h:column> <h:column> <f:facet name="header">Código</f:facet> #{usuario.codigo} </h:column> <h:column> <h:graphicImage library="imagens" name="bandeira_#{usuario.idioma}.png" /> </h:column> <h:column> <f:facet name="header">Nome</f:facet> #{usuario.nome} </h:column> <h:column> <f:facet name="header">e-Mail</f:facet> <a href="mailto:#{usuario.email}">#{usuario.email}</a> </h:column> <h:column> <h:commandLink action="#{usuarioBean.editar}">
onclick="if (!confirm('Confirma a exclusão do usuário #{usuario.nome}?')) return false;">
<h:graphicImage library="imagens" name="excluir16.png" style="border:0" />
<f:setPropertyActionListener target="#{usuarioBean.usuario}" value="#{usuario}" />
</h:commandLink> </h:column>
</h:dataTable> </h:form>
</h:body> </html>
Copie e cole esse código no arquivo criado. Não se esqueça que o código em
xhtml no word fica com a indentação um pouco desorganizada isso pode vir
causar algum erro na página.
Passo 4: Acesse o link abaixo e efetue o download de um arquivo zip, que
possui as imagens que iremos usar em nossa aplicação.
https://sites.google.com/site/wleandrooliveira/programacao-web-ii/aulas-praticas/imagens.zip?attredirects=0&d=1
Ao efetuar o download do arquivo, descompacte e as imagens na pasta imagens
que criamos no diretório resources.
Passo 5: Vamos alterar o código da Classe UsuarioBean.java, altere a classe
conforme o código abaixo:
Observe que já temos essa classe criado e só vamos adicionar os códigos que
estão realçados em amarelo.
Código UsuarioBean.java
package br.com.pitagoras.sistfinanceiro.web;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import br.com.pitagoras.sistfinanceiro.usuario.Usuario.*;
@ManagedBean(name = "usuarioBean")
@RequestScoped
public class UsuarioBean {
private Usuario usuario = new Usuario();
private String confirmarSenha;
private List<Usuario> lista;
private String destinoSalvar;
public String novo() {
this.destinoSalvar = "usuariosucesso";
this.usuario = new Usuario();
this.usuario.setAtivo(true);
return "/publico/usuario";
}
public String editar() {
this.confirmarSenha = this.usuario.getSenha();
return "/publico/usuario";
}
public String salvar() {
FacesContext context = FacesContext.getCurrentInstance();
FacesMessage facesMessage = new FacesMessage("A senha
não foi confirmada corretamente");
context.addMessage(null, facesMessage);
return null;
}
UsuarioRN usuarioRN = new UsuarioRN();
usuarioRN.salvar(this.usuario);
return this.destinoSalvar;
}
public String excluir() {
UsuarioRN usuarioRN = new UsuarioRN();
usuarioRN.excluir(this.usuario);
this.lista = null;
return null;
}
public String ativar() {
if (this.usuario.isAtivo())
this.usuario.setAtivo(false);
else
this.usuario.setAtivo(true);
UsuarioRN usuarioRN = new UsuarioRN();
usuarioRN.salvar(this.usuario);
return null;
}
if (this.lista == null) {
UsuarioRN usuarioRN = new UsuarioRN();
this.lista = usuarioRN.listar();
}
return this.lista;
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public String getConfirmarSenha() {
return confirmarSenha;
}
public void setConfirmarSenha(String confirmarSenha) {
this.confirmarSenha = confirmarSenha;
}
public String getDestinoSalvar() {
return destinoSalvar;
}
public void setDestinoSalvar(String destinoSalvar) {
this.destinoSalvar = destinoSalvar;
}
Passo 6: Vamos adicionar um linha de código em nossa página usuário.xhtml.
Vamos adicionar a linha de código na posição logo abaixo de
<h:inputHidden value="#{usuarioBean.usuario.ativo}" />, conforme a
ilustração abaixo.
<h:body>
<h1>Cadastro de Usuários</h1>
<h:form id="cadastro">
<h:messages />
<h:inputHidden value="#{usuarioBean.usuario.codigo}" />
<h:inputHidden value="#{usuarioBean.usuario.ativo}" />
<h:inputHidden value="#{usuarioBean.destinoSalvar}" />
Passo 7: Vamos fazer uma última alteração da página principal.
Adicione a linha realçada em amarelo, na posição ilustrada abaixo.
<h:commandLink action="#{usuarioBean.excluir}"
onclick="if (!confirm('Confirma a exclusão do usuário
#{usuario.nome}?')) return false;">
<h:graphicImage library="imagens" name="excluir16.png"
style="border:0" />
<f:setPropertyActionListener target="#{usuarioBean.usuario}"
value="#{usuario}" />
<f:setPropertyActionListener target="#{usuarioBean.destinoSalvar}"
value="/admin/principal" />
</h:commandLink>
Laboratório PROGRAMAÇÃO WEB II: Prática 7- Parte 2
Proteção do Aplicativo com Spring Security.
O Spring Framework é um framework java e de código-fonte aberto que
visa facilitar o desenvolvimento JavaEE. Ele é baseado nos padrões de
Inversão de Controle (IoC) e Injeção de Dependências. A Funcionalidade
com base em definições em um arquivo de configuração XML criado pelo
desenvolvedor, resultando um baixo acoplamento entre as classes.
Porém, o Spring fornece também outros que utilizam essa funcionalidade
básica, como Web services com o Spring WebService; O Spring WebFlow,
que fornece alguns recursos para desenvolvimento de aplicativos web e
integração com JavaServer Faces; e Spring Security, que será utilizado
agora.
O Spring Security é um dos projetos Spring mais maduros. Existentes
desde 2003, é utilizado em milhares de projetos pelo mundo, incluindo
agências governamentais e militares.
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>3.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
Passo 2: Vamos adicionar a linha <scope>provided</scope>, à
dependência do conector Java MySQL, conforme ilustrado abaixo:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
<scope>provided</scope>
Isso significa que o conector deverá ser fornecido externamente, por
exemplo podemos fazer o download do jar do conector MySQL e adicionar
ao projeto como uma jar externa ou salvar na pasta do servidor web.
Passo 3: Vamos criar uma pasta com no META-INF no diretório Páginas
Web e dentro desse diretório iremos criar um arquivo com o nome
contexto.xml. A Estrutura deverá ficar igual à figura abaixo.
Vamos codificar o conteúdo do arquivo contexto.xml com o código abaixo.
Código contexto.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context reloadable="true">
<Resource name="jdbc/FinanceiroDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root" password="quimica7295"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/sistfinanceiro?autoReconnect=true" />
Passo 4: Vamos alterar o arquivo web.xml para informar ao servidor web
que o DataSource JNDI criado está disponível.
Adicione o bloco de código ao arquivo web.xml
<resource-ref>
<description>DataSource FinanceiroDB</description>
<res-ref-name>jdbc/FinanceiroDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Adicione esse bloco de código na posição ilustrada na figura abaixo.
Passo 5: Vamos alterar o arquivo Hibernate.cfg.xml será alterado para
não mais conter as configurações do banco de dados, e sim apontar para
Para isso remova as seguintes linhas do arquivo.
E acrescente a linha a seguir.
<property
name="connection.datasource">java:/comp/env/jdbc/FinanceiroDB
</property>
Passo 6: Configuração do Spring Security
Vamos alterar o arquivo web.xml, adicionando o bloco de código abaixo.
<!-- Spring Security -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/applicationContext-security.xml
</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Adicione o bloco de código na posição conforme a figura abaixo.
Observe que adicionamos as duas linhas abaixo:
Iremos criar esses arquivos na pasta WEB-INF, conforme podemos ver na
Agora iremos codificar os arquivos criados.
Código applicationContext-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<http auto-config="true">
<intercept-url pattern="/admin/**" access="ROLE_ADMINISTRADOR" />
<intercept-url pattern="/restrito/**" access="ROLE_USUARIO" />
always-use-default-target="true"
default-target-url="/restrito/principal.jsf"
authentication-failure-url="/publico/login.jsf?login_error=1" />
<logout />
<remember-me />
</http>
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="financeiroDataSource"
authorities-by-username-query="SELECT u.login,
p.permissao
FROM Usuario u, usuario_permissao p
WHERE u.codigo = p.usuario AND u.login = ?"
users-by-username-query="SELECT login, senha, ativo
FROM Usuario WHERE login = ?" />
</authentication-provider>
</authentication-manager>
</beans:beans>
Código applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
<bean id="financeiroDataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/FinanceiroDB</value>
</property>
</bean>
</beans>
Passo 7: Criação da página de Login. Na pasta publico crie um arquivo
com o nome login.xhtml e codifique conforme o código abaixo.
Código login.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Login</title>
</h:head>
<h:body>
<h:panelGroup rendered="#{!empty param.login_error}">
<span style="color: red"> Erro ao efetuar o login.</span>
<br />
<br />
Motivo: #{SPRING_SECURITY_LAST_EXCEPTION.message}
<form id="login" method="post"
action="#{request.contextPath}/j_spring_security_check">
<table>
<tr>
<td>Login</td>
<td><input
type='text'
name='j_username'
/></td>
</tr>
<tr>
<td>Senha</td>
<td><input type='password' name='j_password'
/></td>
</tr>
<tr>
<td align="right"><input type="checkbox"
name="_spring_security_remember_me"
/></td>
<td>Logar automaticamente</td>
</tr>
<tr>
<td></td>
<td><input
type="submit"
value="Logar"
/></td>
</table>
<script>
document.getElementById("login").j_username.value
=
"#{SPRING_SECURITY_LAST_USERNAME}";
</script>
</form>
</h:body>
</html>
Passo 8: Alterar a Página index.xhtml, conforme o código abaixo.
Vamos adicionar o código realçado em amarelo, na página index.xhtml.
Código index.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Financeiro</title>
</h:head>
<h:body>
<h1>Financeiro</h1>
<h:form>
<h:commandLink action="#{usuarioBean.novo}">Novo
usuário</h:commandLink>
<br />
</h:form>
</h:body>
</html>
Passo 9: Vamos criar a pasta restrito e a página principal.xhtml do
diretório restrito. Conforme a figura abaixo.
Vamos codificar a página principal.xhtml da pasta restrito conforme o
código abaixo:
Código principal.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Principal</title>
</h:head>
<h:body>
Usuário logado #{request.remoteUser}
<br />
<h:form>
<h:panelGroup
rendered="#{request.isUserInRole('ROLE_ADMINISTRADOR')}">
<h:commandLink
action="/admin/principal"
title="Administrativo">
<h:graphicImage
library="imagens"
name="administrativo16.png" />
</h:commandLink>
</h:panelGroup>
<a
onclick="document.location='#{request.contextPath}/j_spring_sec
urity_logout'"
title="Sair"> <h:graphicImage library="imagens"
name="logout16.png" />
</a>
</h:form>
</h:body>
</html>
Passo 10: Preparação do Sistema para gerenciar as permissões.
•
Mapeamento da Tabela de permissões no Hibernate;
•
Alterações da regra de negócio do usuário para que este receba as
permissões-padrão no momento do cadastro.
•
Alterações da listagem de usuários para que seja possível atribuir
permissões aos usuários.
Mapeamento da tabela de permissões no Hibernate
Código Usuario.java
package br.com.pitagoras.sistfinanceiro.usuario;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.UniqueConstraint;
@Entity
public class Usuario implements Serializable {
@Id
@GeneratedValue
private Integer codigo;
private String nome;
private String email;
@org.hibernate.annotations.NaturalId
private String login;
private Date nascimento;
private String celular;
private String idioma;
private boolean ativo;
@ElementCollection(targetClass = String.class)
@JoinTable(name = "usuario_permissao", uniqueConstraints = {
@UniqueConstraint(columnNames = { "usuario",
"permissao" }) }, joinColumns = @JoinColumn(name = "usuario"))
@Column(name = "permissao", length = 50)
private Set<String> permissao = new HashSet<String>();
public Integer getCodigo() {
return codigo;
}
public void setCodigo(Integer codigo) {
this.codigo = codigo;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getLogin() {
return login;
public void setLogin(String login) {
this.login = login;
}
public String getSenha() {
return senha;
}
public void setSenha(String senha) {
this.senha = senha;
}
public Date getNascimento() {
return nascimento;
}
public void setNascimento(Date nascimento) {
this.nascimento = nascimento;
}
public String getCelular() {
return celular;
}
public void setCelular(String celular) {
this.celular = celular;
}
public String getIdioma() {
return idioma;
}
public void setIdioma(String idioma) {
this.idioma = idioma;
}
return ativo;
}
public void setAtivo(boolean ativo) {
this.ativo = ativo;
}
public Set<String> getPermissao() {
return permissao;
}
public void setPermissao(Set<String> permissao) {
this.permissao = permissao;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (ativo ? 1231 : 1237);
result = prime * result + ((celular == null) ? 0 :
celular.hashCode());
result = prime * result + ((codigo == null) ? 0 :
codigo.hashCode());
result = prime * result + ((email == null) ? 0 : email.hashCode());
result = prime * result + ((idioma == null) ? 0 :
idioma.hashCode());
result = prime * result + ((login == null) ? 0 : login.hashCode());
result = prime * result + ((nascimento == null) ? 0 :
nascimento.hashCode());
result = prime * result + ((nome == null) ? 0 : nome.hashCode());
result = prime * result + ((permissao == null) ? 0 :
permissao.hashCode());
result = prime * result + ((senha == null) ? 0 : senha.hashCode());
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Usuario other = (Usuario) obj;
if (ativo != other.ativo)
return false;
if (celular == null) {
if (other.celular != null)
return false;
} else if (!celular.equals(other.celular))
return false;
if (codigo == null) {
if (other.codigo != null)
return false;
} else if (!codigo.equals(other.codigo))
return false;
if (email == null) {
if (other.email != null)
return false;
} else if (!email.equals(other.email))
return false;
if (idioma == null) {
if (other.idioma != null)
return false;
} else if (!idioma.equals(other.idioma))
return false;
if (login == null) {
if (other.login != null)
return false;
} else if (!login.equals(other.login))
return false;
if (nascimento == null) {
if (other.nascimento != null)
} else if (!nascimento.equals(other.nascimento))
return false;
if (nome == null) {
if (other.nome != null)
return false;
} else if (!nome.equals(other.nome))
return false;
if (permissao == null) {
if (other.permissao != null)
return false;
} else if (!permissao.equals(other.permissao))
return false;
if (senha == null) {
if (other.senha != null)
return false;
} else if (!senha.equals(other.senha))
return false;
return true;
}
}
Dica o código acima, da classe Usuario.java está completo, o que
atualizamos foi o bloco de código realçados em amarelo, e posteriormente
foi gerado os gets e sets e os métodos hashcode e equals. Logo pode
apagaro conteúdo da classe e colar o código completo na classe.
Passo 11: Vamos alterar a classe UsuarioDAOHibernate.java para que as
informações de Permissões de usuários não sejam perdida na hora de
inserir dados no banco.
Vamos alterar o método atualizar da classe UsuarioDAOHibernate.java.
public void atualizar(Usuario usuario) {
if (usuario.getPermissao() == null || usuario.getPermissao().size() == 0)
{
Usuario usuarioPermissao = this.carregar(usuario.getCodigo());
usuario.setPermissao(usuarioPermissao.getPermissao());
this.session.evict(usuarioPermissao);
}
this.session.update(usuario);
}
Observe que o código realçado em amarelo é a parte que adicionaremos nesta classe.
Alteração do cadastro de usuário para atribuir a permissão padrão
Iremos alterar a classe UsuarioRN.java, e o único método afetado, ou seja,
alterado, será o método salvar.
public void salvar(Usuario usuario) {
Integer codigo = usuario.getCodigo();
if (codigo == null || codigo == 0) {
usuario.getPermissao().add("ROLE_USUARIO");
this.usuarioDAO.salvar(usuario);
} else {
this.usuarioDAO.atualizar(usuario);
}
}
Observe que a única linha alterada está realçada em amarelo.
Alterações da administração de usuário para atribuir permissões.
Nosso usuário terá 3 tipos de permissões:
•
ROLE_USUARIO;
O Código-fonte completo da coluna Permissões, incluída na listagem de
usuários, pode ser visto a seguir. Aplique o trecho de código entre as
<h:column> já existentes. O arquivo principal.xhtml está na pasta admin.
Código principal.xhtml
<h:column>
<f:facet name="header">Permissões</f:facet>
<h:commandLink
action="#{usuarioBean.atribuiPermissao(usuario,
'ROLE_ADMINISTRADOR')}"
title="Permissão Administrador">
<h:graphicImage library="imagens"
name="ROLE_ADMINISTRADOR_#{usuario.permissao.contains('ROLE_ADMINIS
TRADOR')}.png"
style="border:0" />
</h:commandLink>
<h:commandLink
action="#{usuarioBean.atribuiPermissao(usuario,
'ROLE_USUARIO_VIP')}"
title="Permissão Usuário VIP">
<h:graphicImage library="imagens"
name="ROLE_USUARIO_VIP_#{usuario.permissao.contains('ROLE_USUARIO_VI
P')}.png"
style="border:0" />
</h:commandLink>
Passo 12: Agora iremos fazer a ultima alteração, essa alteração será na
classe UsuarioBean.java, vamos adicionar o método atribuiPermissao,
conforme mostrado abaixo.
Código UsuarioBean.java
public String atribuiPermissao(Usuario usuario, String permissao) {
this.usuario = usuario;
java.util.Set<String> permissoes = this.usuario.getPermissao();
if (permissoes.contains(permissao)) {
permissoes.remove(permissao);
} else {
permissoes.add(permissao);
}
return null;