Cícero Ednilson

Blog sobre Desenvolvimento de Softwares

Home » Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 4: Configurando o Spring Security.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 4: Configurando o Spring Security.

Nessa parte do nosso tutorial vamos configurar o Spring Security que já está no nosso projeto com Spring Boot, alem de configurar o Spring Security vamos também criar a página de login da nossa aplicação.

Páginas do tutorial.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 1: Introdução.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 2: Criando os objetos do banco de dados.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 3: Montando o projeto com Spring Boot.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 4: Configurando o Spring Security.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 5: Criando Layout com Thymeleaf.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 6: Criando o cadastro de usuário.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 7: Criando a consulta de usuário.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 8: Excluindo um usuário cadastrado.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 9: Editando um usuário cadastrado.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 10: Testando os acessos do sistema.

Criando uma aplicação Web com Spring Boot, Thymeleaf, Material Designer Lite e Oracle – Parte 11: Executando a aplicação sem o Tomcat Embedded.

Criando as entidades para validação.

Primeiro vamos criar as entidades que vamos usar para realizarmos a validação de usuário, grupo e permissões, no nosso projeto vamos criar o pacote br.com.ciceroednilson.webapp.entity, depois vamos adcionar nesse pacote a classe com o nome de UsuarioEntity, essa entidade vai ser responsável por persistir a nossa tabela tb_usuario, depois vamos deixar a nossa classe com o código abaixo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
 
package br.com.ciceroednilson.webapp.entity;
 
import java.io.Serializable;
import java.util.List;
 
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
 
 
@Table(name="tb_usuario", schema="cicero")
@Entity
public class UsuarioEntity implements Serializable {
 
	private static final long serialVersionUID = 1L;
 
	@Id
	@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq_id_usuario")
	@SequenceGenerator(name="seq_id_usuario", sequenceName="seq_id_usuario")  	
	@Column(name="id_usuario")
	private Long	codigo;
 
	@Column(name="ds_nome")
	private String	nome;
 
	@Column(name="ds_login")
	private String login;
 
	@Column(name="ds_senha")
	private String senha;
 
	@Column(name="fl_ativo")
	private boolean ativo;
 
        @JoinTable(name = "TB_USUARIO_X_GRUPO", 
    	joinColumns = {@JoinColumn(name = "ID_USUARIO", referencedColumnName = "ID_USUARIO")}, 
	inverseJoinColumns = {@JoinColumn(name = "ID_GRUPO", referencedColumnName = "ID_GRUPO")}
        )
	@ManyToMany(cascade ={ CascadeType.PERSIST, CascadeType.MERGE})	
	private List<GrupoEntity> grupos;
 
 
	public Long getCodigo() {
		return codigo;
	}
 
	public void setCodigo(Long codigo) {
		this.codigo = codigo;
	}
 
	public String getNome() {
		return nome;
	}
 
	public void setNome(String nome) {
		this.nome = nome;
	}
 
	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 boolean isAtivo() {
		return ativo;
	}
 
	public void setAtivo(boolean ativo) {
		this.ativo = ativo;
	}
 
	public List<GrupoEntity> getGrupos() {
		return grupos;
	}
 
	public void setGrupos(List<GrupoEntity> grupos) {
		this.grupos = grupos;
	}
}

Agora vamos criar a entidade GrupoEntity no pacote br.com.ciceroednilson.webapp.entity, essa entidade vamos usar para persistir a tabela tb_grupo, depois vamos deixar a nossa entidade com o código abaixo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package br.com.ciceroednilson.webapp.entity;
 
import java.io.Serializable;
import java.util.List;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
 
@Table(name="tb_grupo", schema="cicero")
@Entity
public class GrupoEntity implements Serializable {
 
	private static final long serialVersionUID = 1L;
 
	@Id
	@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq_id_grupo")
	@SequenceGenerator(name="seq_id_grupo", sequenceName="seq_id_grupo")  	
	@Column(name="id_grupo")
	private Long codigo;
 
	@Column(name="ds_nome")
	private String nome;
 
	@Column(name="ds_descricao")
	private String descricao;
 
	@ManyToMany
	@JoinTable(
	name="TB_USUARIO_X_GRUPO",
	joinColumns=@JoinColumn(name="id_grupo", referencedColumnName="id_grupo"),
	inverseJoinColumns=@JoinColumn(name="id_usuario", referencedColumnName="id_usuario")
	)
	private List<UsuarioEntity> usuarios;
 
	@ManyToMany
	@JoinTable(
	name="TB_PERMISSAO_X_GRUPO",
	joinColumns=@JoinColumn(name="id_grupo", referencedColumnName="id_grupo"),
	inverseJoinColumns=@JoinColumn(name="id_permissao", referencedColumnName="id_permissao")
	)
	private List<PermissaoEntity> permissoes;
 
 
	public Long getCodigo() {
		return codigo;
	}
 
	public void setCodigo(Long codigo) {
		this.codigo = codigo;
	}
 
	public String getNome() {
		return nome;
	}
 
	public void setNome(String nome) {
		this.nome = nome;
	}
 
	public String getDescricao() {
		return descricao;
	}
 
	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}
 
	public List<UsuarioEntity> getUsuarios() {
		return usuarios;
	}
 
	public void setUsuarios(List<UsuarioEntity> usuarios) {
		this.usuarios = usuarios;
	}
 
	public List<PermissaoEntity> getPermissoes() {
		return permissoes;
	}
 
	public void setPermissoes(List<PermissaoEntity> permissoes) {
		this.permissoes = permissoes;
	}
 
}

Agora vamos criar a entidade PermissaoEntity no pacote br.com.ciceroednilson.webapp.entity, essa entidade vamos usar para persistir a tabela tb_permissao, depois vamos deixar a nossa entidade com o código abaixo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package br.com.ciceroednilson.webapp.entity;
 
 
import java.io.Serializable;
import java.util.List;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
 
@Table(name="tb_permissao", schema="cicero")
@Entity
public class PermissaoEntity implements Serializable {
 
	private static final long serialVersionUID = 1L;
 
	@Id
	@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq_id_permissao")
	@SequenceGenerator(name="seq_id_permissao", sequenceName="seq_id_permissao")  	
	@Column(name="id_permissao")	
	private Long codigo;
 
	@Column(name="ds_permissao")	
	private String permissao;
 
	@Column(name="ds_descricao")	
	private String descricao;	
 
	@ManyToMany(mappedBy = "permissoes")
	private List<GrupoEntity> grupos;
 
	public Long getCodigo() {
		return codigo;
	}
 
	public void setCodigo(Long codigo) {
		this.codigo = codigo;
	}
 
	public String getPermissao() {
		return permissao;
	}
 
	public void setPermissao(String permissao) {
		this.permissao = permissao;
	}
 
	public String getDescricao() {
		return descricao;
	}
 
	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}
 
	public List<GrupoEntity> getGrupos() {
		return grupos;
	}
 
	public void setGrupos(List<GrupoEntity> grupos) {
		this.grupos = grupos;
	}
 
 
}

Abaixo podemos ver no nosso projeto as entidades que criamos.

Entidades criadas

Agora vamos criar um pacote com o nome de br.com.ciceroednilson.webapp.repository, e nesse pacote vamos adicionar uma Interface com o nome de UsuarioRepository.

1
2
3
4
5
6
7
8
9
10
11
package br.com.ciceroednilson.webapp.repository;
 
import org.springframework.data.jpa.repository.JpaRepository;
 
import br.com.ciceroednilson.webapp.entity.UsuarioEntity;
 
public interface UsuarioRepository extends JpaRepository<UsuarioEntity, Long> {
 
	UsuarioEntity findByLogin(String login);
 
}

Quando usamos o Spring Data não precisamos nos preocupar em montar a query nem usar o EntityManager para execução dos comandos SQL, o Spring Data já resolve tudo isso para nós, podemos perceber que na Interface acima temos um método que consulta o usuário pelo login, isso está sendo possível por que estamos herdando a Interface JpaRepository e no nosso método estamos usando o prefixo findByLogin, atráves desse prefixo o Spring já sabe que deve ser realizada uma consulta pelo campo login.

Ainda no pacote br.com.ciceroednilson.webapp.repository vamos criar uma Interface com o nome de GrupoRepository, essa Interface vai ter um método para consultar os grupos de um determinado usuário, vamos deixar a nossa interface com o código abaixo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package br.com.ciceroednilson.webapp.repository;
 
import java.util.List;
 
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
 
import br.com.ciceroednilson.webapp.entity.GrupoEntity;
import br.com.ciceroednilson.webapp.entity.UsuarioEntity;
 
@Repository
public interface GrupoRepository extends JpaRepository<GrupoEntity, Long>{
 
	List<GrupoEntity> findByUsuariosIn(UsuarioEntity usuarioEntity);
 
}

Ainda no pacote br.com.ciceroednilson.webapp.repository vamos criar um Interface com o nome de PermissaoRepository, e depois vamos deixar essa Interface com o código abaixo, essa Interface tem apenas um método para consultar as permissões de um grupo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package br.com.ciceroednilson.webapp.repository;
 
import java.util.List;
 
import org.springframework.data.jpa.repository.JpaRepository;
 
import br.com.ciceroednilson.webapp.entity.GrupoEntity;
import br.com.ciceroednilson.webapp.entity.PermissaoEntity;
 
 
public interface PermissaoRepository extends JpaRepository<PermissaoEntity, Long> {
 
	List<PermissaoEntity> findByGruposIn(GrupoEntity grupoEntity);
}

Abaixo podemos ver no nosso projeto as Interfaces que criamos.

Agora vamos criar um pacote com o nome de br.com.ciceroednilson.webapp.model, nesse pacote vamos criar as classes que vamos usar na interação das nossas views, vamos criar primeiro a classe GrupoModel, essa classe vamos usar para preencher os checkbox com os grupos cadastrados no nosso banco de dados, vamos deixar o código da nossa classe como mostra abaixo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package br.com.ciceroednilson.webapp.model;
 
public class GrupoModel {
 
	private Long codigo;
	private String nome;	
	private String descricao;
	private Boolean checked;
 
	public GrupoModel(){
 
	}
 
	public GrupoModel(Long codigo, String nome, String descricao) {
		super();
		this.codigo = codigo;
		this.nome = nome;
		this.descricao = descricao;
	}
	public GrupoModel(Long codigo,String descricao) {
		super();
		this.codigo = codigo;	
		this.descricao = descricao;
	}
 
	public Long getCodigo() {
		return codigo;
	}
	public void setCodigo(Long codigo) {
		this.codigo = codigo;
	}
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	public String getDescricao() {
		return descricao;
	}
	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}
	public Boolean getChecked() {
		return checked;
	}
 
	public void setChecked(Boolean checked) {
		this.checked = checked;
	}
 
 
}

Agora vamos criar a classe UsuarioModel, essa classe vai ser usada para receber as informações de usuários na view, vamos deixar nossa classe com o código abaixo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package br.com.ciceroednilson.webapp.model;
 
import java.time.LocalDate;
import java.util.List;
 
import org.hibernate.validator.constraints.NotEmpty;
 
public class UsuarioModel {
 
	private Long	  codigo;
 
	@NotEmpty(message ="O Nome é de preenchimento obrigatório.")
	private String	  nome;
 
	@NotEmpty(message ="O Login é de preenchimento obrigatório.")
	private String   login;
 
	@NotEmpty(message ="A Senha é de preenchimento obrigatório.")
	private String   senha;
 
	private boolean ativo;
 
	@NotEmpty(message ="Não existe nenhum grupo selecionado.")
	private  List<Long> grupos; 
 
	public UsuarioModel(){
 
		System.out.println("Passei " + LocalDate.now());
	}
 
	public UsuarioModel(Long codigo, String nome, String login, String senha, boolean ativo, List<Long> grupos) {
		super();
		this.codigo = codigo;
		this.nome = nome;
		this.login = login;
		this.senha = senha;
		this.ativo = ativo;
		this.grupos = grupos;
	}	
 
	public Long getCodigo() {		
		return codigo;
	}
 
	public void setCodigo(Long codigo) {
		this.codigo = codigo;
	}
 
	public String getNome() {
		return nome;
	}
 
	public void setNome(String nome) {
		this.nome = nome;
	}
 
	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 boolean isAtivo() {
		return ativo;
	}
 
	public void setAtivo(boolean ativo) {
		this.ativo = ativo;
	}
 
	public List<Long> getGrupos() {
		return grupos;
	}
 
	public void setGrupos(List<Long> grupos) {
		this.grupos = grupos;
	}
 
}

Agora vamos criar uma classe com o nome de UsuarioSecurityModel, essa classe o Spring vai usar para dar as devidas permissões para o usuário, devemos deixar o código como mostra abaixo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package br.com.ciceroednilson.webapp.model;
 
 
import java.util.Collection;
 
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
 
public class UsuarioSecurityModel extends User {
 
	private static final long serialVersionUID = 1L;
 
	public UsuarioSecurityModel(String login, String senha,Boolean ativo,  Collection<? extends GrantedAuthority> authorities) {		
		super(login, senha, ativo,	true, true,true, authorities);
	}	
}

Abaixo podemos ver no nosso projeto o pacote e as classes que criamos.

Agora vamos criar o pacote br.com.ciceroednilson.webapp.service, esse pacote vai conter as classes que vão acessar as nossas informações no banco de dados, depois de criar o pacote vamos criar a classe GrupoService, essa classe vai ter um método que retorna todos os grupos cadastrados no Banco de Dados, vamos deixar a nossa classe com o código abaixo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package br.com.ciceroednilson.webapp.service;
 
 
import java.util.ArrayList;
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import br.com.ciceroednilson.webapp.entity.GrupoEntity;
import br.com.ciceroednilson.webapp.model.GrupoModel;
import br.com.ciceroednilson.webapp.repository.GrupoRepository;
 
@Service
@Transactional
public class GrupoService {
 
	@Autowired
	private GrupoRepository grupoRepository;
 
	/**CONSULA OS GRUPOS CADASTRADOS*/
	@Transactional(readOnly = true)
	public List<GrupoModel> consultarGrupos(){
 
		List<GrupoModel> gruposModel =  new ArrayList<GrupoModel>();
 
		/*CONSULTA TODOS OS GRUPOS*/
		List<GrupoEntity> gruposEntity = this.grupoRepository.findAll();
 
 
	    gruposEntity.forEach(grupo ->{ 
		   gruposModel.add(new GrupoModel(grupo.getCodigo(), grupo.getDescricao())); 
	    });
 
		return gruposModel;
	}
 
}

Agora vamos criar a classe UsuarioService e vamos deixar ela com o código abaixo, para entender os métodos dessa classe leia os comentários descritos no código.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
package br.com.ciceroednilson.webapp.service;
 
 
import java.util.ArrayList;
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
 
import br.com.ciceroednilson.webapp.entity.GrupoEntity;
import br.com.ciceroednilson.webapp.entity.PermissaoEntity;
import br.com.ciceroednilson.webapp.entity.UsuarioEntity;
import br.com.ciceroednilson.webapp.model.UsuarioModel;
import br.com.ciceroednilson.webapp.model.UsuarioSecurityModel;
import br.com.ciceroednilson.webapp.repository.GrupoRepository;
import br.com.ciceroednilson.webapp.repository.PermissaoRepository;
import br.com.ciceroednilson.webapp.repository.UsuarioRepository;
 
@Component
public class UsuarioService  implements UserDetailsService {
 
	@Autowired
	private UsuarioRepository usuarioRepository;
 
	@Autowired
	private GrupoRepository grupoRepository; 
 
	@Autowired
	private PermissaoRepository permissaoRepository;
 
	/***
	 * CONSULTA UM USUÁRIO POR LOGIN
	 */
	@Override
	public UserDetails loadUserByUsername(String login) throws BadCredentialsException,DisabledException {
 
		UsuarioEntity usuarioEntity = usuarioRepository.findByLogin(login);
 
		if(usuarioEntity == null)
			throw new BadCredentialsException("Usuário não encontrado no sistema!");
 
		if(!usuarioEntity.isAtivo())
			throw new DisabledException("Usuário não está ativo no sistema!");
 
		return new UsuarioSecurityModel(
				usuarioEntity.getLogin(), 
				usuarioEntity.getSenha(), 
				usuarioEntity.isAtivo(), 
				this.buscarPermissoesUsuario(usuarioEntity));
	}
 
	/***
	 * BUSCA AS PERMISSÕES DO USUÁRIO
	 * @param usuarioEntity
	 * @return
	 */
	public List<GrantedAuthority> buscarPermissoesUsuario(UsuarioEntity usuarioEntity) {
 
		List<GrupoEntity> grupos = grupoRepository.findByUsuariosIn(usuarioEntity);
 
		return this.buscarPermissoesDosGrupos(grupos);
	}
 
	/***
	 * BUSCA AS PERMISSÕES DO GRUPO
	 * */
	public List<GrantedAuthority> buscarPermissoesDosGrupos(List<GrupoEntity> grupos) {
		List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
 
		for (GrupoEntity grupo: grupos) {
 
			List<PermissaoEntity> lista = permissaoRepository.findByGruposIn(grupo);
 
			for (PermissaoEntity permissao: lista) {
				auths.add(new SimpleGrantedAuthority(permissao.getPermissao()));
			}
		}
 
		return auths;
	}
 
	/***
	 * SALVA UM NOVO REGISTRO DE USUÁRIO
	 * @param usuarioModel
	 */
	public void salvarUsuario(UsuarioModel usuarioModel){
 
		UsuarioEntity usuarioEntity =  new UsuarioEntity();
 
		/*SETA O USUÁRIO COMO ATIVO NO SISTEMA*/
		usuarioEntity.setAtivo(true);
 
		/*LOGIN DO USUÁRIO*/
		usuarioEntity.setLogin(usuarioModel.getLogin());
 
		/*NOME DO USUÁRIO A SER SALVO*/
		usuarioEntity.setNome(usuarioModel.getNome());
 
		/*CRIPTOGRAMA E INFORMA A SENHA*/
		usuarioEntity.setSenha(new BCryptPasswordEncoder().encode(usuarioModel.getSenha()));
 
 
		/*PEGANDO A LISTA DE GRUPOS SELECIONADOS*/
		GrupoEntity grupoEntity = null;
		List<GrupoEntity> grupos =  new ArrayList<GrupoEntity>();
		for (Long codigoGrupo : usuarioModel.getGrupos()){
 
 
			if(codigoGrupo != null){
 
				/*CONSULTA GRUPO POR CÓDIGO*/	
				grupoEntity = grupoRepository.findOne(codigoGrupo);
 
				/*ADICIONA O GRUPO NA LISTA*/
				grupos.add(grupoEntity);
			}
		}
 
		/*SETA A LISTA DE GRUPO DO USUÁRIO*/
		usuarioEntity.setGrupos(grupos);
 
		/*SALVANDO O REGISTRO*/
		this.usuarioRepository.save(usuarioEntity);
	}	
 
	/***
	 * CONSULTA OS USUÁRIOS CADASTRADOS
	 * @return
	 */
	public List<UsuarioModel> consultarUsuarios(){
 
		List<UsuarioModel> usuariosModel = new ArrayList<UsuarioModel>();
 
		List<UsuarioEntity> usuariosEntity = this.usuarioRepository.findAll();
 
		usuariosEntity.forEach(usuarioEntity ->{
 
			usuariosModel.add(
					new UsuarioModel(usuarioEntity.getCodigo(),
							usuarioEntity.getNome(), 
							usuarioEntity.getLogin(), 
							null, 
							usuarioEntity.isAtivo(),
							null));
		});
 
 
		return usuariosModel;
	}
 
	/**
	 * DELETA UM USUÁRIO  PELO CÓDIGO
	 * */
	public void excluir(Long codigoUsuario){
 
		this.usuarioRepository.delete(codigoUsuario);
	}
 
	/***
	 * CONSULTA UM USUÁRIO PELO SEU CÓDIGO
	 * @param codigoUsuario
	 * @return
	 */
	public UsuarioModel consultarUsuario(Long codigoUsuario){
 
		UsuarioEntity usuarioEntity = this.usuarioRepository.findOne(codigoUsuario);
 
		List<Long> grupos =  new ArrayList<Long>();
 
		usuarioEntity.getGrupos().forEach(grupo ->{
 
			grupos.add(grupo.getCodigo());
 
		}); 
 
		return new UsuarioModel(
				usuarioEntity.getCodigo(),
				usuarioEntity.getNome(),
				usuarioEntity.getLogin(),
				null,
				usuarioEntity.isAtivo(),
				grupos);
 
	}
 
	/**
	 * ALTERA AS INFORMAÇÕES DO USUÁRIO
	 * */
	public void alterarUsuario(UsuarioModel usuarioModel){
 
		UsuarioEntity usuarioEntity =  this.usuarioRepository.findOne(usuarioModel.getCodigo());
 
		/*USUÁRIO ATIVO OU INATIVO*/
		usuarioEntity.setAtivo(usuarioModel.isAtivo());
 
		/*LOGIN DO USUÁRIO*/
		usuarioEntity.setLogin(usuarioModel.getLogin());
 
		/*NOME DO USUÁRIO A SER SALVO*/
		usuarioEntity.setNome(usuarioModel.getNome());
 
		/*CRIPTOGRAMA E INFORMA A SENHA*/
		if(!StringUtils.isEmpty(usuarioModel.getSenha()))
		 usuarioEntity.setSenha(new BCryptPasswordEncoder().encode(usuarioModel.getSenha()));
 
 
		/*PEGANDO A LISTA DE GRUPOS SELECIONADOS*/
		GrupoEntity grupoEntity = null;
		List<GrupoEntity> grupos =  new ArrayList<GrupoEntity>();
		for (Long codigoGrupo : usuarioModel.getGrupos()){
 
 
			if(codigoGrupo != null){
 
				/*CONSULTA GRUPO POR CÓDIGO*/	
				grupoEntity = grupoRepository.findOne(codigoGrupo);
 
				/*ADICIONA O GRUPO NA LISTA*/
				grupos.add(grupoEntity);
			}
		}
 
		/*SETA A LISTA DE GRUPO DO USUÁRIO*/
		usuarioEntity.setGrupos(grupos);
 
		/*SALVANDO ALTERAÇÃO DO REGISTRO*/
		this.usuarioRepository.saveAndFlush(usuarioEntity);
	}
 
 
 
 
 
}

Abaixo podemos ver as classes que criamos no nosso projeto.

Agora no pacote br.com.ciceroednilson.webapp vamos adicionar uma classe com o nome de WebSecurityConfig, essa classe que vai gerenciar a segurança da nossa aplicação, vamos deixar nossa classe com o código abaixo.

Não esqueça de ler os comentários para entender como é feita a segurança do nosso sistema.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package br.com.ciceroednilson.webapp;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 
import br.com.ciceroednilson.webapp.service.UsuarioService;
 
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
	@Autowired
	private UsuarioService usuarioRepositoryImpl;
 
	/**
	 * REALIZA AS CONFIGURAÇÕES DE ACESSO
	 * */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
 
 
		http.authorizeRequests()
			/*DETERMINA QUE PARA REALIZAR ESSA REQUEST PRECISA TER UMA DAS PERMISSÕES ABAIXO
		 	* EXEMPLO DA URL: http://localhost:8095/usuario/novoCadastro
		 	* VEJA QUE EM UM ITEM("hasRole('ADMIN')) NÃO ESTOU PASSANDO O PREFIXO ROLE_, ESSE PREFIXO NÃO É OBRIGATÓRIO 
		 	* QUANDO USAMOS o hasRole*/
			.antMatchers("/usuario/novoCadastro").access("hasRole('ADMIN') or hasRole('ROLE_CADASTROUSUARIO')")
			/*DETERMINA QUE PARA REALIZAR ESSA REQUEST PRECISA TER UMA DAS PERMISSÕES ABAIXO
			 * EXEMPLO DA URL: http://localhost:8095/usuario/consultar */
			.antMatchers("/usuario/consultar").access("hasRole('ADMIN') or hasRole('CONSULTAUSUARIO')")
			 /*DETERMINA QUE PARA ACESSAR A PÁGINA INICIAL DA APLICAÇÃO PRECISA ESTÁ AUTENTICADO*/
			.antMatchers("/home").authenticated()
			.anyRequest().authenticated()			
			.and()			
				.formLogin()
				 /*INFORMANDO O CAMINHO DA PÁGINA DE LOGIN, E SE O LOGIN FOR EFETUADO COM SUCESSO
				  *O USUÁRIO DEVE SER REDIRECIONADO PARA /home(http://localhost:8095/home)*/
				.loginPage("/").defaultSuccessUrl("/home",true)
				.permitAll() /*AQUI ESTAMOS INFORMANDO QUE TODOS TEM ACESSO A PÁGINA DE LOGIN*/
			.and()
			     /*AQUI ESTAMOS INFORMANDO QUE QUANDO FOR REDIRECIONADO PARA  O LINK http://localhost:8095/logout
			      *O USUÁRIO DEVE TER SUA SESSÃO FINALIZADA E REDIRECIONADO PARA A PÁGINA DE LOGIN */
				.logout()
				.logoutSuccessUrl("/")
				.logoutUrl("/logout") 
				.permitAll();
 
 
		/*PÁGINA COM A MENSAGEM DE ACESSO NEGADO
		 *QUANDO O USUÁRIO NÃO TER UMA DETERMINADA PERMISSÃO DE ACESSO AO SISTEMA ELE VAI SER REDIRECIONADO
		 *PARA A URL ABAIXO */
		http.exceptionHandling().accessDeniedPage("/acessoNegado");
 
		/*AQUI ESTOU INFORMANDO QUE QUALQUER REQUEST TEM ACESSO AO DIRETÓRIO src/main/resources */
		http.authorizeRequests().antMatchers("/resources/**").permitAll().anyRequest().permitAll();
 
 
 
 
	}
 
 
	@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
 
        /*INFORMA A CRIPTOGRAFIA QUE DEVE SER USADA PARA A SENHA DO USUÁRIO*/				
		auth.userDetailsService(usuarioRepositoryImpl).passwordEncoder(new BCryptPasswordEncoder());
 
    }
	/*
	 * CRIPTOGRAFANDO A SENHA PARA TESTE
	public static void main(String[] args) {
 
		System.out.println(new BCryptPasswordEncoder().encode("123456"));
	}
	*/
}

Lembrando que as permissões do nosso sistema estão cadastradas no banco de dados como mostra a imagem abaixo.

Agora vamos abrir a página index.html que se encontra na pasta templates e vamos deixar ela com o código abaixo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
 
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
	<meta name="description" content="Blog www.ciceroednilson.com.br"/>
	<meta name="author" content="Cícero Ednilson"/>
 
	<link  rel="stylesheet" href="css/material.min.css"/>	
	<style type="text/css">
		.mdl-layout {
			align-items: center;
		  justify-content: center;
		}
		.mdl-layout__content {
			padding: 24px;
			flex: none;
		}
	</style>
 
	<script type="text/javascript" src="js/material.min.js"></script>	
	<title>Login</title>
</head>
<body>
 
 
<form action="#" th:action="@{/}"  method="post">
 
<div class="mdl-layout mdl-js-layout mdl-color--blue-grey-100">
 
	<div class="mdl-layout__content">
 
		<div class="mdl-card mdl-shadow--6dp">
			<div class="mdl-card__title mdl-color--primary mdl-color-text--white">
				<h2 class="mdl-card__title-text">LOGIN</h2>
			</div>
 
	  		<div class="mdl-card__supporting-text">
 
 
					<span th:if="${param.error}">						
					    <span style='color:red' th:text="${session.SPRING_SECURITY_LAST_EXCEPTION.message}"></span>
					</span>
 
					<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
					    <input class="mdl-textfield__input" type="text" id="input-usuario" name="username"/>
					    <label class="mdl-textfield__label" for="input-usuario">Usuário:</label>
					 </div>
 
					 <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
					    <input class="mdl-textfield__input" type="password" id="input-senha" name="password"/>
					    <label class="mdl-textfield__label" for="input-senha">Senha:</label>
					 </div>
 
			</div>
 
 
			<div class="mdl-card__actions mdl-card--border" style="text-align:right;">
 
			  <button class="mdl-button mdl-button--colored mdl-js-button" >
			  		Esqueci a senha
			  </button>
 
			  <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
				Acessar
 			  </button>
 
 			  <!-- LEIA SOBRE CSRF AQUI
 			  	https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html
 			   -->
 			  <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
 
			</div>
 
		</div>
	</div>
</div>
</form>
 
 
</body>
</html>

Atenção: Veja que no nosso formulário de login estamos usando o parâmetro CSRF, para entender para que serve esse item acesse o link https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html.

Agora vamos clicar com o botão direito sobre a nossa classe WebappApplication e vamos até Run As -> Java Application para inciar a nossa aplicação, depois vamos acessar a url http://localhost:8095/, e então devemos ver a página abaixo.

Depois que a página for carregada vamos informar o usuário abaixo.

usuário:cicero
senha:123456

Depois de efetuar o login o sistema vai tentar redirecionar o usuário para a home page, porem ainda não criamosa essa página, e então vamos ver o erro da imagem abaixo.

Atenção: A configuração de redirecionamento está na classe WebSecurityConfig que criamos nossos passos anteriores.

Na próxima parte do nosso tutorial vamos criar à página home, uma página de acesso negado para ser exibida quando o usuário não tiver permissão de acesso, e à página de template com os menus.

Até a próxima.

Comentários

Name of author

Name: ciceroednilson@gmail.com

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *