Buscar

Springboot Security

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 50 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 50 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 50 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Spring Security
No mundo da tecnologia, em especial da Internet, nenhuma aplicação em execução na
Nuvem pode ficar sem algum �po de Segurança habilitada, devido aos inúmeros perigos
existentes no mundo virtual como ataques Hackers, invasões de Servidores, roubos de
dados, entre outros. No ecossistema Spring, isso é feito com a ajuda da Dependência
Spring Security.
Vamos adicionar a Dependência Spring Security no Projeto Blog Pessoal, adicionando
as linhas abaixo no arquivo pom.xml, Salvar e Executar a aplicação:
<dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-security</artifactId> 
</dependency> 
Abra a sua aplicação no Navegador da Internet através do endereço:
h�p://localhost:8080 e veja o que acontece.
http://localhost:8080/
Como num passe de mágica…
… Você tem uma página de login gerada automa�camente.
… Você não pode mais executar solicitações GET, POST, PUT e DELETE.
… Todo o seu aplica�vo está bloqueado e solicita que você insira um nome de
usuário e uma senha, que não existe.
Tendo sobrevivido ao susto inicial, você deve ter pensado: Como tudo isso aconteceu?
1. Segurança da Aplicação
Antes de estudarmos a Spring Security, vamos compreender 3 conceitos importantes da
Segurança da Informação:
1.1. Auten�cação
É o primeiro processo da Segurança da Informação, popularmente conhecido como
Login no sistema. É o momento em que o usuário informa o seu usuário de acesso (e-
mail) e a sua senha (criptografada), e o sistema fará a checagem se estas informações
estão corretas.
1.2. Autorização
É o segundo processo da Segurança da Informação, popularmente conhecido como
Direitos de acesso (Roles) no sistema. É o momento em que o sistema checará o que o
usuário pode e não pode fazer no sistema, ou seja, as suas permissões dentro do sistema
(Quais Recursos e Endpoints podem ser acessados?).
1.3. Filtros de Servlet
Qualquer aplica�vo da web Spring é apenas um Servlet (é uma Classe Java usada para
criar aplicações WEB), que redireciona todas as Requisições HTTP recebidas (por
exemplo, do Front-end Angular ou React), para as suas respec�vas Classes
Controladoras (@RestControllers).
Como nestas requisições não existe uma segurança e a auten�cação e a autorização
devem ser efetuadas antes das Requisições HTTP, a Spring Security oferece como
solução para este problema os Filtros, que na prá�ca são Objetos que interceptam toda
e qualquer Requisição HTTP recebida antes de chegarem ao controlador. Por isso que o
seu Blog Pessoal está “trancado” após a inserção da Dependência Spring Security.
A figura acima, ilustra o filtro BasicAuthen�ca�onFilter checando o Token de
Autorização do Usuário enviado no cabeçalho da requisição. Como ele está dentro do
padrão Basic, o filtro libera o envio da requisição para a Classe Controladora específica.
A Dependência Spring Security ao ser inserida, habilita 15 filtros, onde cada um tem
uma função específica e precisam ser configurados. Não abordaremos este assunto em
detalhes por ser muito extenso, além de demandar tempo e dedicação, de qualquer
forma você já sabe como a sua aplicação ficou totalmente bloqueada. A Imagem abaixo
mostra os 15 filtros:
2. Spring Security
Analisando nossos projetos podemos perceber que nossa API, até este momento, não
possuía nenhuma segurança, ou seja, qualquer pessoa poderia acessar todos os nossos
endpoints e ter acesso à todos os recursos livremente. Precisamos entender que
algumas aplicações contém informações vitais como: dados pessoais, dados bancários,
usuário e senha de acesso, e portanto precisamos garan�r que a nossa API e estes dados
estejam devidamente protegidos. E para isto podemos contar com a dependência do
Spring chamada Spring Security (adicionada acima).
A Spring Security é um framework para Java, que provê auten�cação, autorização,
filtros e diversas outras funcionalidades para aplicações corpora�vas, com o obje�vo de
proteger a nossa aplicação contra acessos indevidos. Iniciado em 2003 por Ben Alex, a
Spring Security é distribuída sob a licença Apache Licence. Ela oferece diversos recursos
que permitem que muitas prá�cas comuns de segurança sejam implementadas ou
configuradas de forma direta.
O esquema de auten�cação que u�lizaremos em nosso projeto é o HTTP Basic, onde
entraremos com o e-mail (usuário) e a senha do usuário e através de um endpoint
liberado, o Spring Security irá criptografar a senha e fazer uma consulta no nosso Banco
de dados para saber se o usuário já existe. Esta checagem será feita através da Camada
de Serviço (service) da aplicação. Se a consulta encontrar o usuário e a senha, a Spring
Security devolverá como resposta um Authoriza�on com o prefixo Basic + token. Este
token ficará registrado na nossa aplicação na camada de Security, e apenas por meio
dele que o usuário poderá consumir a API.
Para melhor compreensão deste sistema, é necessário dividi-lo em 2 ecossistemas:
Usuário e Segurança, que veremos mais a frente.
3. Conhecendo HTTP authen�ca�on
O IETF (Internet Engineering Task Force) tem como missão iden�ficar e propor soluções
para as questões/problemas relacionados à u�lização da Internet, além de propor a
padronização das tecnologias e protocolos envolvidos. O mesmo define a estrutura de
auten�cação HTTP que pode ser usada por um servidor para definir uma solicitação do
cliente. O servidor responde ao cliente com uma mensagem do �po HTTP Status
401(Não autorizado) e fornece informações de como autorizar com um cabeçalho de
resposta WWW-Authen�cate contendo ao menos uma solicitação. Um cliente que
deseja auten�car-se com um servidor pode fazer isso incluindo um campo de cabeçalho
de solicitação WWW-Authen�cate com as credenciais. No Diagrama de Sequência
abaixo pode se observar este relacionamento:
No caso de uma autorização “Basic” (como a mostra a figura acima), a troca deve
acontecer por meio de uma conexão HTTP (TLS) para ser segura. Se um servidor recebe
credenciais válidas, mas que não são adequadas para ter acesso a um determinado
recurso, o servidor responderá com o código de status HTTP Status 403 (Proibido!) . Ao
contrário de HTTP Status 401(Não autorizado), a auten�cação é impossível para este
usuário. O cabeçalho de requisição Authoriza�on contém as credenciais para auten�car
um agente de usuário com um servidor. Aqui o �po é novamente necessário, seguido
pelas credenciais, que podem ser codificadas ou criptografadas dependendo do
esquema de auten�cação usado. No caso acima foi u�lizado o esquema de auten�cação
Basic que será explicado na sequencia.
 Documentação: HTTP Status Code 401 - Unauthorized
 Documentação: HTTP Status Code 403 - Forbidden
 Documentação: Cabeçalho HTTP WWW-Authen�cate
 Documentação: Cabeçalho de Requisição HTTP Authoriza�on
https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Status/401
https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Status/403
https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/WWW-Authenticate
https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/Authorization
3.1. Esquema de auten�cação Basic
A estrutura geral de auten�cação HTTP é usado por vários esquemas de auten�cação.
Os esquemas podem divergir na força da segurança e na disponibilidade do so�ware
cliente ou servidor. O esquema mais comum de auten�cação é o “Basic”, mas existem
outros esquemas oferecidos por serviços de hospedagem, como Amazon AWS, Google
ou Microso�. Os esquemas de auten�cação mais comuns são:
Esquema de auten�cação Documentação
Basic [RFC7617]
Bearer [RFC6750]
Digest [RFC7616]
HOBA [RFC7486, Sec�on 3]
Mutual [RFC8120]
Nego�ate [RFC4559, Sec�on 3]
OAuth [RFC5849, Sec�on 3.5.1]
SCRAM-SHA-1 [RFC7804]
SCRAM-SHA-256 [RFC7804]
vapid [RFC 8292, Sec�on 3]
ATENÇÃO: Para melhor compreensão no momento, vamos focar
apenas no entendimento do formato Basic, que é considerado o
principal esquema para compreender os demais meios de
autorização. Vale mencionar que para aprender os demais é
necessário tempo e muita dedicação.
O esquemaBasic, segundo sua documentação, consiste em um conjunto de caracteres
que posicionados após a palavra "Basic " no formato “email:senha” codificados
u�lizando o modelo Base64, formando um token Authoriza�on para ser passado ao
sistema. Abaixo veremos um exemplo de código para gerar a estrutura em Java:
https://www.iana.org/go/rfc7617
https://www.iana.org/go/rfc6750
https://www.iana.org/go/rfc7616
https://www.iana.org/go/rfc7486
https://www.iana.org/go/rfc8120
https://www.iana.org/go/rfc4559
https://www.iana.org/go/rfc5849
https://www.iana.org/go/rfc7804
https://www.iana.org/go/rfc7804
https://www.iana.org/go/rfc8292
Dependência:
<!-- Dependência para Codificação do Token --> 
<dependency> 
 <groupId>commons-codec</groupId> 
 <artifactId>commons-codec</artifactId> 
</dependency> 
Exemplo de código em java:
O resultado do código acima proporciona o retorno de um esquema de auten�cação
Basic respeitando as regras ja definidas pela IETF (Internet Engineering Task Force).
Exemplo:
Usuário: admin@email.com.br
Senha: admin123
Token gerado: Basic YWRtaW5AZW1haWwuY29tLmJyOmFkbWluMTIz
ALERTA DE BSM: Mantenha a Atenção aos Detalhes ao escrever o
formato Basic, o mesmo é representado da palavra "Basic " com um
espaço na frente + a criptografia de um conjunto de caracteres
(email:senha) fornecidos ao se auten�car no sistema. No link abaixo
é possível testar a codificação 64 bits.
 Site: Codificador 64 bits
O Token gerado será enviado no Header (cabeçalho) de uma requisição ao servidor
devidamente configurado para acessar os seus recursos.
import java.nio.charset.Charset; 
import org.apache.commons.codec.binary.Base64; 
 
private static String geradorBasicToken(String email, String senha) { 
 String estrutura = email + ":" + senha; 
 byte[] estruturaBase64 = 
 Base64.encodeBase64(estrutura.getBytes(Charset.forName("US-ASCII")))
 return "Basic " + new String(estruturaBase64); 
} 
mailto:admin@email.com.br
https://www.base64url.com/
Projeto 02 - Blog Pessoal - Spring Security
01
O que veremos por aqui:
1. O Ecossistema do Usuário
2. Apresentação do Recurso Usuário
3. Criar a Classe Model Usuario relacionada com a Classe Postagem
4. Criar a Classe UsuarioLogin
5. Criar a Interface UsuarioRepository
1. Ecossistema do Usuario
No Diagrama de Classes acima, é possível visualizar por completo o ecossistema do
Usuário, que representa uma das principais implementações, que permitem que o
sistema de auten�cação baseado nos detalhes do usuário (UserDetail) funcione. A cor
de cada uma das classe representa o pacote onde cada Classe deve ser construída.
segundo as informações da Legenda. Para melhor compreensão das relações entre as
Classes, veja abaixo uma breve definição sobre as relações entre os Objetos:
Relação Descrição
Dependência Classe A pode ser afetada por mudanças na classe B;
Associação Objeto A sabe sobre objeto B. Classe A depende de B;
Agregação
Objeto A sabe sobre objeto B, e consiste de B. Classe A depende
de B;
Composição
Objeto A sabe sobre objeto B, consiste de B, e gerencia o ciclo de
vida de B. Classe A depende de B;
Implementação
Classe A define métodos declarados na interface B. objetos de A
podem ser tratados como B. Classe A depende de B;
Herança
Classe A herda a interface e implementação da classe B mas
pode estende-la. Objetos de A podem ser tratados como B.
Classe A depende de B.
Após compreender o Diagrama de Classes acima e aprender um pouco sobre UML,
segue a aplicação do código em cada uma de suas classes.
ATENÇÃO: Aproveite para validar seu código do Blog Pessoal, o
projeto abaixo serve como espelho para o projeto. Tenha bastante
atenção aos detalhes, pois existem implementações fundamentais
para o perfeito funcionamento do sistema. Caso surjam dúvidas, não
hesite em buscar os Instrutores Genera�on para obter orientações.
2. O Recurso Usuario
Nesta etapa vamos começar a construir o Recurso Usuario, que será composto por 2
Classes: Usuario e Usuario Login.
A Classe Usuario servirá de modelo para construir a tabela tb_usuario (En�dade) dentro
do nosso Banco de dados db_blogpessoal. Os campos (Atributos) da tabela serão os
mesmos que estão definidos no Diagrama de Classes acima. Além de construirmos a
Classe Usuario, também faremos o Relacionamento com as Classe Postagem, construída
anteriormente. Veja como ficará o Relacionamento entre as 3 Classes, após a
implementação, no Diagrama de Classes abaixo:
Na sequência vamos construir a Interface UsuarioRepository, que irá nos auxiliar na
interação com o Banco de dados e com as Classes UsuarioController, onde serão
implementados os 5 métodos descritos no Diagrama de Classes acima e com a Classe de
Serviço (Service), UsuarioService, onde serão implementadas as Regras de Negócio
exigidas pela Spring Security.
O Diagrama de Classes da nossa Interface UsuarioRepository será igual a imagem
abaixo:
Depois de criar a Classe Model Usuario e Relacionamento com a Classe Postagem, a
estrutura do nosso Banco de dados db_blogpessoal ficará igual ao Diagrama de
En�dade e Relacionamentos (DER) abaixo:
Observe que a en�dade Postagem (tb_postagem) passará a ter 2 Chaves Estrangeiras
(FK): tema_id e usuario_id.
O Dicionário de dados da nossa tabela tb_Usuario será o seguinte:
Atributo Tipo de dado Descrição Chave
id bigint Iden�ficador único PK
nome varchar(255) Nome do usuário
usuario varchar(255) E-mail do usuário
senha varchar(255) Senha do usuário
foto varchar(5000) Foto do usuário
ALERTA DE BSM: Mantenha a Atenção aos Detalhes ao criar o Recurso
Usuario. Todas as Camadas (Pacotes: Model, Repository e Controller), já
foram criadas nos Recursos Postagem e Tema.
ALERTA DE BSM: Mantenha a Atenção aos Detalhes ao criar o Recurso
Usuario. Todas as Camadas (Pacotes: Model, Repository e Controller), já
foram criadas nos Recursos Postagem e Tema.
DICA: Caso você tenha alguma dúvida sobre como criar a Classe, executar
o projeto, entre outras, consulte a Documentação dos Recursos Postagem
e Tema.
Além da Classe Usuario e da Interface UsuarioRepository, criaremos a Classe Usuario
Login, que embora seja criada na Camada Model, ela não irá gerar uma tabela no Banco
de dados. Esta Classe será uma Classe auxiliar para o usuário efetuar login no sistema.
👣 Passo 01 - Checar as Dependências
No arquivo, pom.xml, adicione as linhas abaixo (caso ainda não tenha adicionado
alguma delas):
<!-- Dependência da Spring Security --> 
<dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-security</artifactId> 
</dependency> 
 
 
<!-- Dependência para Codificação do Token --> 
<dependency> 
 <groupId>commons-codec</groupId> 
 <artifactId>commons-codec</artifactId> 
</dependency> 
 Código fonte: pom.xml
👣 Passo 02 - Criar a Classe Usuario na Camada Model
Agora vamos criar a terceira Classe Model que chamaremos de Usuario.
1. Clique com o botão direito do mouse sobre o Pacote Model
(com.genera�on.blogpessoal.model), na Source Folder Principal (src/main/java),
e clique na opção New 🡪 Class
2. Na janela New Java Class, no item Name, digite o nome da Classe (Usuario), e na
sequência clique no botão Finish para concluir.
A seguir, veja a sua implementação:
package com.generation.blogpessoal.model; 
 
import java.util.List; 
 
import javax.persistence.CascadeType; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.OneToMany; 
import javax.persistence.Table; 
import javax.validation.constraints.Email; 
import javax.validation.constraints.NotBlank; 
import javax.validation.constraints.NotNull; 
import javax.validation.constraints.Size; 
 
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 
 
@Entity 
@Table(name = "tb_usuarios") 
https://github.com/conteudoGeneration/blog-pessoal/blob/12-Blog-(Security_PomXML_Model_Usuario_And_UserLogin)/blogpessoal/pom.xml
public class Usuario{ 
 
 @Id 
 @GeneratedValue(strategy = GenerationType.IDENTITY) 
 private Long id; 
 
 @NotNull(message = "O atributo Nome é Obrigatório!") 
 private String nome; 
 
 @Size(max = 5000, 
 message = "O link da foto não pode ser maior do que 5000 caracteres") 
 private String foto; 
 
 @NotNull(message = "O atributo Usuário é Obrigatório!") 
 @Email(message = "O atributo Usuário deve ser um email válido!") 
 private String usuario; 
 
 @NotBlank(message = "O atributo Senha é Obrigatório!") 
 @Size(min = 8, message = "A Senha deve ter no mínimo 8 caracteres") 
 private String senha; 
 
 @OneToMany(mappedBy = "usuario", cascade = CascadeType.REMOVE) 
 @JsonIgnoreProperties("usuario") 
 private List<Postagem> postagem; 
 
 /* Insira os Getters and Setters */ 
 public Long getId() { 
 return id; 
 } 
 
 public void setId(Long id) { 
 this.id = id; 
 } 
 
 public String getNome() { 
 return nome; 
 } 
 
 public void setNome(String nome) { 
 this.nome = nome; 
 } 
 
 public String getFoto() { 
 return foto; 
 } 
 
 public void setFoto(String foto) { 
 this.foto = foto; 
 } 
 
 public String getUsuario() { 
 return usuario; 
 } 
 
 public void setUsuario(String usuario) { 
 this.usuario = usuario; 
 } 
 
 public String getSenha() { 
 return senha; 
 } 
 
 public void setSenha(String senha) { 
 this.senha = senha; 
 } 
 
 public List<Postagem> getPostagem() { 
 return postagem; 
 } 
 
 public void setPostagem(List<Postagem> postagem) { 
 this.postagem = postagem; 
 } 
} 
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, o atributo senha
definido acima, não pode conter o atributo size max, que limita seu
tamanho máximo. Dependendo do limite inserido, pode provocar um
erro 500, devido ao limite de caracteres que serão u�lizados na
criptografia. Deixe apenas com size min configurado.
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, o atributo de
relacionamento definido como postagem, possui a anotação
@OneToMany com a opção cascade type = REMOVE. Se o seu projeto
es�ver com ALL, ao deletar uma postagem você apagará também o
usuário, pois este relacionamento tem uma dependência de pai e filho.
Mantenha como REMOVE para que isso não aconteça
Para concluir, não esqueça de Salvar o código (File 🡪 Save All).
👣 Passo 03 - Criar a Relação ManytoOne na Classe
Postagem
A Classe Postagem será o lado N:1, ou seja, Muitas Postagens podem ter apenas Um
Usuario. Para criar a Relação vamos inserir depois do úl�mo atributo da Classe
Postagem (tema), as 3 linhas destacadas em vermelho na figura abaixo:
Não esqueça de acrescentar acrescentar os Métodos Get e Set para o novo atributo
(usuario), que foi adicionado na Classe Postagem.
DICA: Toda vez que você adicionar um novo Atributo na sua Classe, não
esqueça de criar os Métodos GET e SET do Atributo. Caso contrário, você não
conseguirá visualizar ou atualizar os dados do Atributo.
👣 Passo 04 - Criar a Classe UsuarioLogin na Camada
Model
Agora vamos criar a quarta Classe Model que chamaremos de UsuarioLogin.
A classe UsuarioLogin é responsável por definir que o cliente ao tentar auten�car (fazer
login) no sistema, forneça apenas o usuário (e-mail) e a senha. Essa classe também pode
ser definida como uma DTO (Data trasfer object), que é uma classe que é u�lizada para
transitar dados do sistema sem revelar sua Classe Model para o cliente.
1. Clique com o botão direito do mouse sobre o Pacote Model
(com.genera�on.blogpessoal.model), na Source Folder Principal (src/main/java),
e clique na opção New 🡪 Class
2. Na janela New Java Class, no item Name, digite o nome da Classe (UsuarioLogin),
e na sequência clique no botão Finish para concluir.
A seguir veja sua implementação:
package com.generation.blogpessoal.model; 
 
public class UsuarioLogin { 
 
 private Long id; 
 private String nome; 
 private String usuario; 
 private String foto; 
 private String senha; 
 private String token; 
 
 public Long getId() { 
 return id; 
 } 
 
 public void setId(Long id) { 
 this.id = id; 
 } 
 
 public String getNome() { 
 return nome; 
 } 
 
 
 
 public void setNome(String nome) { 
 this.nome = nome; 
 } 
 
 public String getUsuario() { 
 return usuario; 
 } 
 
 public String getFoto() { 
 return foto; 
 } 
 
 public void setFoto(String foto) { 
 this.foto = foto; 
 } 
 
 public String getToken() { 
 return token; 
 } 
 
 public void setToken(String token) { 
 this.token = token; 
 } 
 
 public void setUsuario(String usuario) { 
 this.usuario = usuario; 
 } 
 
 public String getSenha() { 
 return senha; 
 } 
 
 public void setSenha(String senha) { 
 this.senha = senha; 
 } 
} 
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, não se esqueça
de passar o id do usuario como atributo da classe, pois este atributo
será u�lizado como crdencial pelo front-end para pegar o usuario pelo
id. Todos os atributos presentes na Classe Model Usuario devem estar
presentes na Classe UsuarioLogin.
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, não se esqueça
de passar o id do usuario como atributo da classe, pois este atributo
será u�lizado como crdencial pelo front-end para pegar o usuario pelo
id. Todos os atributos presentes na Classe Model Usuario devem estar
presentes na Classe UsuarioLogin.
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, não esquecer
também do atributo token, pois o mesmo será passado no cabeçalho
de todas as requisições que do front-end. Este atributo é fundamental
para o funcionamento do consumo da api.
Para concluir, não esqueça de Salvar o código (File 🡪 Save All).
👣 Passo 05 - Executar o projeto e Checar o Banco de
dados
1. Execute o projeto e verifique no Console se a tabela tb_usuario foi criada.
2. Verifique também no MySQL Workbench se a tabela tb_usuario foi criada no
Banco de dados db_blogpessoal com o respec�vo relacionamento.
👣 Passo 06 - Criar a Interface UsuarioRepository na
Camada Repository
Agora vamos criar a Interface Repository que chamaremos de UsuarioRepository.
1. Clique com o botão direito do mouse sobre o Pacote Repository
(com.genera�on.blogpessoal.repository), na Source Folder Principal
(src/main/java):
2. Na sequência, clique na opção New 🡪 Interface
3. Na janela New Java Interface, no item Name, digite o nome da Interface
(PostagemRespository), e na sequência clique no botão Finish para concluir.
A seguir veja sua implementação:
package com.generation.blogpessoal.repository; 
 
import java.util.List; 
import java.util.Optional; 
 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.stereotype.Repository; 
 
import com.generation.blogpessoal.model.Usuario; 
 
@Repository 
public interface UsuarioRepository extends JpaRepository<Usuario, Long>{ 
 
 public Optional<Usuario> findByUsuario(String usuario); 
 
} 
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, tome muito
cuidado pois se a escrita dos métodos findBy ou findAllBy es�ver
errada, pode aparecer um erro no console do STS.
Observe que foi criada uma Query Method na Interface UsuarioRepository, conforme
detalhado abaixo:
Query Method
public Optional<Usuario> findByUsuario(String usuario); 
Instrução SQL equivalente
SELECT * FROM tb_usuario WHERE usuario = "usuario"; 
Palavra Instrução SQL
find 🡪 SELECT
By 🡪 WHERE
Usuario 🡪 Atributo da Classe Usuario
Palavra Instrução SQL
String
usuario
🡪 Parâmetro do Método contendo o e-mail do usuário que você
deseja procurar.
ATENÇÃO: A instrução FROM tb_usuario será inserida pelo JPA ao
checar o nome da tabela gerada pela Classe Usuario.
Para concluir, não esqueça de Salvar o código (File 🡪 Save All).
 Código fonte: Camada Model e Repository
https://github.com/conteudoGeneration/blog-pessoal/tree/15-Blog-(Security_UserDetailsService_And_UserRepository)
Projeto 02 - Blog Pessoal - Spring Security
02
O que veremos por aqui:
1. O Ecossistema da Segurança
2. A Classe UserDetailsImpl
3. A Classe UserDetailsServiceImpl
4. A Classe BasicSecurityConfigAntes de finalizarmos o Ecossistema do Usuário, vamos compreender e implementar o
Ecossistema da Segurança, porquê u�lizaremos alguns Métodos deste ecossistema na
implementação das Classes UsuarioService e UsuarioController.
1. Ecossistema da Segurança
No Diagrama de Classes acima, é possível visualizar por completo o ecossistema da
Segurança, que representa uma das principais implementações de segurança do sistema.
Nesta implementação é possível realizar a auten�cação do usuário a par�r de um Banco
de dados. Para isso é necessário enviar as informações necessárias para que a Spring
Security valide a permissão do usuário no sistema. O ecossistema de segurança consiste
de uma classe de configuração (BasicSecurityConfig), uma de Classe Serviço
(UserDetailsService) e uma Classe Model (UserDetailsImpl). A cor de cada uma das
Classes representa o pacote onde cada uma deve ser implementada, segundo
informações da legenda. Para este Diagrama de Classes, repare que a Classe Model do
Usuario e o Repositório do Usuário já foram criadas anteriormente. Para melhor
compreensão das relações entre as Classes veja uma breve definição sobre as relações
entre os Objetos:
Relação Descrição
Dependência Classe A pode ser afetada por mudanças na classe B;
Associação Objeto A sabe sobre objeto B. Classe A depende de B;
Agregação
Objeto A sabe sobre objeto B, e consiste de B. Classe A depende
de B;
Composição
Objeto A sabe sobre objeto B, consiste de B, e gerencia o ciclo de
vida de B. Classe A depende de B;
Implementação
Classe A define métodos declarados na interface B. objetos de A
podem ser tratados como B. Classe A depende de B;
Herança
Classe A herda a interface e implementação da classe B mas
pode estende-la. Objetos de A podem ser tratados como B.
Classe A depende de B.
Após compreender o Diagrama de Classes acima e aprender um pouco sobre UML,
segue a aplicação do código em cada uma de suas Classes.
👣 Passo 01 - Criar o Pacote Security
Primeiro vamos criar a camada de segurança, ou seja, o Pacote Security, onde as Classes
serão implementadas:
1. No lado esquerdo superior, na Guia Package explorer, clique com o botão direito
do mouse sobre a Package com.genera�on.blogpessoal, na Source Folder
src/main/java e clique na opção New 🡪 Package.
2. Na janela New Java Package, no item Name, acrescente no final do nome da
Package .security, como mostra a figura abaixo:
3. Clique no botão Finish para concluir.
👣 Passo 02 - Criar a Classe UserDetailsImpl na Camada
Security
Esta classe implementa a Interface UserDetails, que tem como principal funcionalidade
fornecer as informações básicas do usuário para a Spring Security. Ao criar esta Classe,
será permi�do que uma Classe de Serviço (Service), preencha os atributos através do
Método Construtor e retorne apenas o necessário para que a Spring Security possa
validar o usuário que está tentando acessar o sistema.
1. Clique com o botão direito do mouse sobre o Pacote Security
(com.genera�on.blogpessoal.security), na Source Folder Principal
(src/main/java), e clique na opção New 🡪 Class
2. Na janela New Java Class, no item Name, digite o nome da Classe
(UserDetailsImpl), e na sequência clique no botão Finish para concluir.
ATENÇÃO: Por se tratar de uma Implementação de uma Interface
(UserDetails), todos os Métodos da Interface devem ser implementados e o
nome da Classe deve obrigatoriamente conter o sufixo Impl (Implements),
indicando que a Classe está Implementando a Interface.
Vejamos abaixo a implementação da Classe:
package com.generation.blogpessoal.security; 
 
import java.util.Collection; 
import java.util.List; 
 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.userdetails.UserDetails; 
 
import com.generation.blogpessoal.model.Usuario; 
 
public class UserDetailsImpl implements UserDetails{ 
 
private static final long serialVersionUID =1L; 
 
 private String userName; 
 private String password; 
 
 private List<GrantedAuthority> authorities; 
 
 public UserDetailsImpl (Usuario user){ 
 this.userName = user.getUsuario(); 
 this.password = user.getSenha(); 
 } 
 
 public UserDetailsImpl (){} 
 
 @Override 
 public Collection<? extends GrantedAuthority> getAuthorities() { 
 
 return authorities; 
 } 
 
 @Override 
 public String getPassword() { 
 
 return password; 
 } 
 
 @Override 
 public String getUsername() { 
 
 return userName; 
 } 
 
 @Override 
 public boolean isAccountNonExpired() { 
 
 return true; 
 } 
 
 @Override 
 public boolean isAccountNonLocked() { 
 
 return true; 
 } 
 
 @Override 
 public boolean isCredentialsNonExpired() { 
 
 return true; 
 } 
 
 
 
 
 @Override 
 public boolean isEnabled() { 
 
 return true; 
 } 
 
} 
Para concluir, não esqueça de Salvar o código (File 🡪 Save All).
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, é necessário ter
um construtor adaptado para receber atributos que serão u�lizados
para logar no sistema. Os atributos em questão são usuário e senha,
mas poderia ser também e-mail e senha. Tudo irá depender de como a
model de Usuario esta elaborada.
ATENÇÃO: *Observe que o Método getAuthori�es(), que retorna a
lista com os direitos de acesso do usuário, sempre retornará uma List
vazia, porquê este atributo não pode ser Nulo. Com o obje�vo de
simplificar a implementação, todo o Usuário auten�cado terá todos os
direitos de acesso sobre a aplicação. *
 Documentação: UserDetails
 Documentação: GrantedAuthority
👣 Passo 03 - Criar a Implementação da Classe
UserDetailsServiceImpl
Esta Classe é uma implementação da Interface UserDetailsService, responsável por
fornecer a estrutura de um método u�lizado pela Spring Security para validar a
existência de um usuário no Banco de dados e retornar um UserDetails. Com os dados
fornecidos ao sistema, será possível auten�car um usuario baseando-se na sua
existência no banco. Vale lembrar que para isso é necessário que ao salvar o usuário, sua
senha esteja criptografada (Veremos na implementação da Classe UsuarioService),
u�lizando uma biblioteca de criptografia válida para o sistema de segurança.
https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/core/userdetails/UserDetails.html
https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/core/GrantedAuthority.html
1. Clique com o botão direito do mouse sobre o Pacote Security
(com.genera�on.blogpessoal.security), na Source Folder Principal
(src/main/java), e clique na opção New 🡪 Class
2. Na janela New Java Class, no item Name, digite o nome da Classe
(UserDetailsServiceImpl), e na sequência clique no botão Finish para concluir.
ATENÇÃO: Por se tratar de uma Implementação de uma Interface
(UserDetailsService), todos os Métodos da Interface devem ser
implementados e o nome da Classe deve obrigatoriamente conter o sufixo
Impl (Implements), indicando que a Classe está Implementando a Interface.
Vejamos abaixo a implementação da Classe:
package com.generation.blogpessoal.security; 
 
import java.util.Optional; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.security.core.userdetails.UserDetails; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import 
org.springframework.security.core.userdetails.UsernameNotFoundException; 
import org.springframework.stereotype.Service; 
 
import com.generation.blogpessoal.model.Usuario; 
import com.generation.blogpessoal.repository.UsuarioRepository; 
 
@Service 
public class UserDetailsServiceImpl implements UserDetailsService { 
 
 @Autowired 
 private UsuarioRepository repository; 
 
 @Override 
 public UserDetails loadUserByUsername(String userName) 
 throws UsernameNotFoundException { 
 
 Optional<Usuario> usuario = repository.findByUsuario(userName); 
 usuario.orElseThrow(() -> new UsernameNotFoundException(userName + " 
 
 return usuario.map(UserDetailsImpl::new).get();} 
} 
Observe que na linha return usuario.map(UserDetailsImpl::new).get();, a Classe
Retorna um objeto do �po UserDetailsImpl criado com os dados recuperados do Banco
de dados. O operador :: faz parte de uma expressão que referencia um Método,
complementando uma função Lambda. Neste exemplo, o operador faz referência ao
Método Construtor da Classe UserDetailsImpl. Esta instrução poderia é equivalente ao
seguinte comando: return new UserDetailsImpl(op�onal.get());.
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, ao criar este
serviço não esquecer de colocar a anotação @Service. Desta forma o
Spring entenderá que a classe é um serviço e fará o carregamento
com prioridade para esta classe.
 Documentação: UserDetailsService
👣 Passo 04 - Criar a Classe BasicSecurityConfig
Esta Classe é u�lizada para sobrescrever a configuração já predefinida pela Spring
Security para a segurança. A Classe possui a anotação @EnableWebSecurity, que
habilita e sobrescreve os Métodos que irão redefinir as regras de Segurança de acordo
com as Regras da sua aplicação.
1. Clique com o botão direito do mouse sobre o Pacote Security
(com.genera�on.blogpessoal.security), na Source Folder Principal
(src/main/java), e clique na opção New 🡪 Class
2. Na janela New Java Class, no item Name, digite o nome da Classe
(BasicSecurityConfig), e na sequência clique no botão Finish para concluir.
package com.generation.blogpessoal.security; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Bean; 
import org.springframework.http.HttpMethod; 
import org.springframework.security.config.annotation.authentication 
.builders.AuthenticationManagerBuilder; 
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; 
https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/core/userdetails/UserDetailsService.html
import org.springframework.security.config.http.SessionCreationPolicy; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 
import org.springframework.security.crypto.password.PasswordEncoder; 
 
@EnableWebSecurity 
public class BasicSecurityConfig extends WebSecurityConfigurerAdapter { 
 
 @Autowired 
 private UserDetailsService userDetailsService; 
 
 @Override 
 protected void configure(AuthenticationManagerBuilder auth) 
 throws Exception { 
 auth.userDetailsService(userDetailsService); 
 
 auth.inMemoryAuthentication() 
 .withUser("root") 
 .password(passwordEncoder().encode("root")) 
 .authorities("ROLE_USER"); 
 } 
 
 @Bean 
 public PasswordEncoder passwordEncoder() { 
 return new BCryptPasswordEncoder(); 
 } 
 
 @Override 
 protected void configure(HttpSecurity http) 
 throws Exception { 
 http.authorizeRequests() 
 .antMatchers("/usuarios/logar").permitAll() 
 .antMatchers("/usuarios/cadastrar").permitAll() 
 .antMatchers(HttpMethod.OPTIONS).permitAll() 
 .anyRequest().authenticated() 
 .and().httpBasic() 
 .and().sessionManagement() 
 .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
 .and().cors() 
 .and().csrf().disable(); 
 } 
} 
 
Na implementação acima a anotação @Bean no método passwordEncoder() , indica ao
Spring Security que a aplicação está baseada em algum modelo de criptografia, que será
implementada no Método PasswordEncoder. Para esta aplicação estamos u�lizando o
modelo BCryptPasswordEncoder(). Vale ressaltar que esta criptografia está sendo
esperada para analisar a senha que estamos guardando no Banco de dados.
Dica: No primeiro link abaixo você pode conhecer mais sobre o BCrypt e
no segundo link testar a codificação e a decodificação de Strings através
do BCrypt.
 Ar�go: Uma breve introdução sobre BCrypt
 Site: Codificador BCrypt
Quando sobrescrevemos o método ***configure(Authen�ca�onManagerBuilder
auth)***, estamos informando ao spring que a configuração de auten�cação será
redefinida em sua implementação. Neste método estamos fornecendo duas formas de
auten�cação:
.userDetailsService(userDetailsService): u�liza um serviço para pesquisar a credencial
do usuário no Banco de dados.
.inMemoryAuthen�ca�on(): u�liza um usuário em memória, no caso definido no
próprio método, como usuário root e senha root.
Para mais detalhes sobre esta definição, o mais correto é olhar sua fonte no link abaixo:
 Documentação: Authen�ca�onManagerBuilder
Quando sobrescrevemos o método ***configure(H�pSecurity h�p)***, estamos
informando ao Spring que a configuração por padrão definida será alterada. Nesta
configuração é possivel customizar de diferentes maneiras a sua aplicação.
.authorizeRequests(): podemos definir quais endpoints poderão acessar o sistema sem
precisar de auten�cação. No caso acima foi definido que os endpoints logar e cadastrar
serão autorizados para todos os usuários, enquanto para os demais endpoints será
necessário auten�car.
.antMatchers("/usuarios/logar").permitAll() e
.antMatchers("/usuarios/cadastrar").permitAll(): permite definir o caminho do endpoint
que estará acessível sem auten�cação.
https://medium.com/reprogramabr/uma-breve-introdu%C3%A7%C3%A3o-sobre-bcrypt-f2fad91a7420
https://bcrypt-generator.com/
https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.html
ATENÇÃO: Os endpoints cadastrar e logar foram liberados porquê caso
contrário ninguém conseguirá acessar a aplicação. Além disso, é
fundamental que os endereços dos endpoints: /usuarios/logar e
/usuarios/cadastrar estejam definidos na implementação da Classe
UsuarioController.
ATENÇÃO: Os endpoints cadastrar e logar foram liberados porquê caso
contrário ninguém conseguirá acessar a aplicação. Além disso, é
fundamental que os endereços dos endpoints: /usuarios/logar e
/usuarios/cadastrar estejam definidos na implementação da Classe
UsuarioController.
.antMatchers(H�pMethod.OPTIONS).permitAll(): O parâmetro H�pMethod.OPTIONS
permite que o cliente (frontend), possa descobrir quais são as opções permi�das em
uma requisição, para um determinado recurso em um servidor. Nesta implementação,
está sendo liberada todas as opções das requisições através do método .permitAll().
.anyRequest().authen�cated(): informa ao sistema que todas as demais rotas que não
es�verem especificadas no escopo do authorizeRequests(), deverão ser auten�cadas.
.h�pBasic(): informa ao sistema que o servidor irá receber requisições que devem ter o
esquema HTTP Basic de auten�cação. Desta forma habilitamos o servidor para que as
requisições tenham um formato específico de auten�cação.
.sessionManagement().sessionCrea�onPolicy(SessionCrea�onPolicy.STATELESS):
define que o nosso sistema não guardará sessões para o cliente. Quando o cliente faz
uma solicitação HTTP, ele inclui todas as informações necessárias para o servidor
atender à solicitação. O servidor nunca dependerá de informações de solicitações
anteriores do cliente. Se alguma dessas informações for importante, o cliente a enviará
novamente a informação como parte da solicitação atual.
.cors(): libera o acesso de outras origens, desta forma nossa API poderá ser acessada de
outros domínios, ou seja, de outros servidores, além do servidor onde a aplicação está
hospedada.
Exemplo:
.csrf().disable(): desabilita a proteção que vem a�va contra o ataque do �po CSRF
(Cross-Site-Request-Forgery), que seria uma interceptação dos dados de auten�cação
por um Hacker. Esta configuração foi desabilitada porquê o Spring Security fica
procurando por um parâmetro oculto adicional em qualquer requisição POST / PUT /
DELETE, chamado token CSRF. Como ele não vai encontrar, apenas as requisiçõesdo
�po GET seriam aceitas.
Para mais detalhes sobre esta definição, o mais correto é olhar sua fonte no link abaixo:
 Documentação: H�pSecurity
 Documentação: HTTP Status Code 401 - Unauthorized
 Documentação: CORS
 Ar�go: Complete Guide to CSRF/XSRF (Cross-Site Request Forgery)
 Código fonte: Camada Security
https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/config/annotation/web/builders/HttpSecurity.html
https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Methods/OPTIONS
https://developer.mozilla.org/pt-BR/docs/Web/HTTP/CORS
https://reflectoring.io/complete-guide-to-csrf/
https://github.com/conteudoGeneration/blog-pessoal/tree/15-Blog-(Security_UserDetailsService_And_UserRepository)
Projeto 02 - Blog Pessoal - Spring Security
03
O que veremos por aqui:
1. A Classe UsuarioService
2. A Classe UsuarioController
3. Atualização da Classe PostagemController
4. Testes no Postman
Vamos finalizar o Ecossistema do Usuário.
👣 Passo 01 - Criar o Pacote Service
1. Na Guia Package explorer, clique com o botão direito do mouse sobre a Package
com.genera�on.blogpessoal, na Source Folder src/main/java e clique na opção
New 🡪 Package.
2. Na janela New Java Package, no item Name, acrescente no final do nome da
Package .service e clique no botão Finish para concluir.
👣 Passo 02 - Criar a Classe UsuarioService na Camada
Service
A Classe UsuarioService é responsável por manipular as regras de negócio de usuário
no sistema. Esta classe deve ser anotada com a anotação @Service, para que o Spring
iden�fique que é uma classe que serviço e carregue ela sempre que puder. Vale
mencionar que alguns métodos definidos abaixo são de extrema importância para o
sistema.
1. Clique com o botão direito do mouse sobre o Pacote Security
(com.genera�on.blogpessoal.service), na Source Folder Principal (src/main/java),
e clique na opção New 🡪 Class
2. Na janela New Java Class, no item Name, digite o nome da Classe
(UsuarioService), e na sequência clique no botão Finish para concluir.
A seguir veja sua implementação:
package com.generation.blogpessoal.service; 
 
import java.nio.charset.Charset; 
import java.util.Optional; 
 
import org.apache.commons.codec.binary.Base64; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.http.HttpStatus; 
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 
import org.springframework.stereotype.Service; 
import org.springframework.web.server.ResponseStatusException; 
 
import com.generation.blogpessoal.model.Usuario; 
import com.generation.blogpessoal.model.UsuarioLogin; 
import com.generation.blogpessoal.repository.UsuarioRepository; 
 
@Service 
public class UsuarioService { 
 
 @Autowired 
 private UsuarioRepository usuarioRepository; 
 
 
 
 
 public Optional<Usuario> cadastrarUsuario(Usuario usuario) { 
 
 if (usuarioRepository.findByUsuario(usuario.getUsuario()) 
 .isPresent()) 
 throw new ResponseStatusException(HttpStatus.BAD_REQUEST, 
 "Usuário já existe!", null); 
 
 usuario.setSenha(criptografarSenha(usuario.getSenha())); 
 
 return Optional.of(usuarioRepository.save(usuario)); 
 } 
 
 public Optional<Usuario> atualizarUsuario(Usuario usuario) { 
 
 if (usuarioRepository.findById(usuario.getId()).isPresent()) { 
 Optional<Usuario> buscaUsuario = usuarioRepository. 
 findByUsuario(usuario.getUsuario()); 
 
 if (buscaUsuario.isPresent()) { 
 if (buscaUsuario.get().getId() != usuario.getId()) 
 throw new ResponseStatusException(HttpStatus.BAD_REQUEST, 
 "Usuário já existe!", null); 
 } 
 
 usuario.setSenha(criptografarSenha(usuario.getSenha())); 
 
 return Optional.of(usuarioRepository.save(usuario)); 
 } 
 
 throw new ResponseStatusException(HttpStatus.NOT_FOUND, 
 "Usuário não encontrado!", null); 
 } 
 
 public Optional<UsuarioLogin> logarUsuario( 
 Optional<UsuarioLogin> usuarioLogin) { 
 
 Optional<Usuario> usuario = usuarioRepository 
 .findByUsuario(usuarioLogin.get().getUsuario()); 
 
 if (usuario.isPresent()) { 
 if (compararSenhas(usuarioLogin.get().getSenha(), 
 usuario.get().getSenha())) { 
 
 usuarioLogin.get().setId(usuario.get().getId()); 
 usuarioLogin.get().setNome(usuario.get().getNome()); 
 usuarioLogin.get().setFoto(usuario.get().getFoto()); 
Observe que foram criados os Métodos cadastrarUsuario() e atualizarUsuario(), que
criptografam a senha e impedem a duplicação do usuário no Banco de dados. O Método
logarUsuario(), além de auten�car o usuário no sistema, ele compara a senha digitada
pelo usuário com a senha persis�da no Banco de dados e gera o Token do usuário.
 usuarioLogin.get().setToken( 
 generatorBasicToken(usuarioLogin.get().getUsuario(), 
 usuarioLogin.get().getSenha())); 
 usuarioLogin.get().setSenha(usuario.get().getSenha()); 
 
 return usuarioLogin; 
 
 } 
 } 
 
 throw new ResponseStatusException( 
 HttpStatus.UNAUTHORIZED, "Usuário ou senha inválidos!", null); 
 } 
 
 private String criptografarSenha(String senha) { 
 
 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); 
 String senhaEncoder = encoder.encode(senha); 
 
 return senhaEncoder; 
 } 
 
 private boolean compararSenhas(String senhaDigitada, 
 String senhaBanco) { 
 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); 
 
 return encoder.matches(senhaDigitada, senhaBanco); 
 } 
 
 private String generatorBasicToken(String email, String password) { 
 String structure = email + ":" + password; 
 byte[] structureBase64 = Base64 
 .encodeBase64(structure.getBytes(Charset.forName("US-ASCII"))); 
 return "Basic " + new String(structureBase64); 
 } 
 
} 
 
Para executar as operações: Criptografar Senha, Comparar Senhas e Gerar Token foram
criados os respec�vos Métodos auxiliares na própria Classe UsuarioService.
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, o cadastro de
um novo usuário no sistema necessita ser validado no Banco de
dados. Caso o usuário já exista, a aplicação não deve permi�r que ele
seja criado novamente, pois um usuário duplicado no sistema
ocasionará um erro HTTP Status 500.
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, ao atualizar um
usuário é importante que seja validado novamente a criptografia da
senha e o usuário (e-mail). Caso não seja validado ocasionará um
problema ao tentar pegar as credenciais pelo front-end da aplicação.
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, ao u�lizar o
método para logarUsuario, se atentar de que seja passado todos os
parâmetros do usuarioLogin, pois o mesmo será u�lizado pelo front-
end da aplicação.
Para concluir, não esqueça de Salvar o código (File 🡪 Save All).
 Documentação: @Service
 Documentação: BCryptPasswordEncoder - Java Doc Spring
 Documentação: Throw
 Documentação: Métodos de Referência (::)
 Documentação: Base64 - Java Doc Commons
 Código fonte: Classe UsuarioService 
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Service.html
https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.html
https://docs.oracle.com/javase/tutorial/essential/exceptions/throwing.html
https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
https://commons.apache.org/proper/commons-codec/apidocs/index.html
https://github.com/conteudoGeneration/blog-pessoal/blob/16-Blog-(Security_UserService)/blogpessoal/src/main/java/com/generation/blogpessoal/service/UsuarioService.java
👣 Passo 03 - Criar a Classe UsuarioController na
Camada Controller
A classe UsuarioController, é responsável por fornecer o acesso aos recursos do
sistema. Uma das suas funcionalidades abaixo é promover o CRUD do usuário. Além de
permi�r total manipulação do usuário, consumindo os serviços cadastrar usuário,
atualizar usuário e auten�car da Classe UsuarioService.
1. Clique com o botãodireito do mouse sobre o Pacote Security
(com.genera�on.blogpessoal.controller), na Source Folder Principal
(src/main/java), e clique na opção New 🡪 Class
2. Na janela New Java Class, no item Name, digite o nome da Classe
(UsuarioController), e na sequência clique no botão Finish para concluir.
A seguir veja sua implementação:
package com.generation.blogpessoal.controller; 
 
import java.util.List; 
import java.util.Optional; 
 
import javax.validation.Valid; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.http.HttpStatus; 
import org.springframework.http.ResponseEntity; 
import org.springframework.web.bind.annotation.CrossOrigin; 
import org.springframework.web.bind.annotation.GetMapping; 
import org.springframework.web.bind.annotation.PathVariable; 
import org.springframework.web.bind.annotation.PostMapping; 
import org.springframework.web.bind.annotation.PutMapping; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RestController; 
 
import com.generation.blogpessoal.model.Usuario; 
import com.generation.blogpessoal.model.UsuarioLogin; 
import com.generation.blogpessoal.repository.UsuarioRepository; 
import com.generation.blogpessoal.service.UsuarioService; 
 
@RestController 
@RequestMapping("/usuarios") 
@CrossOrigin(origins = "*", allowedHeaders = "*") 
public class UsuarioController { 
 
 @Autowired 
 private UsuarioService service; 
 
 @Autowired 
 private UsuarioRepository repository; 
 
 @GetMapping("/all") 
 public ResponseEntity <List<Usuario>> getAll() { 
 return ResponseEntity.ok(repository.findAll()); 
 } 
 
 @GetMapping("/{id}") 
 public ResponseEntity<Usuario> getById(@PathVariable long id) { 
 return repository.findById(id) 
 .map(resp -> ResponseEntity.ok(resp)) 
 .orElse(ResponseEntity.notFound().build()); 
 } 
 
 @PostMapping("/logar") 
 public ResponseEntity<UsuarioLogin> autenticationUsuario( 
 @RequestBody Optional<UsuarioLogin> usuario) { 
 return service.logarUsuario(usuario) 
 .map(resp -> ResponseEntity.ok(resp)) 
 .orElse(ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()); 
 } 
 
 @PostMapping("/cadastrar") 
 public ResponseEntity<Usuario> postUsuario( 
 @Valid @RequestBody Usuario usuario) { 
 return service.cadastrarUsuario(usuario) 
 .map(resp -> ResponseEntity.status(HttpStatus.CREATED).body(resp)) 
 .orElse(ResponseEntity.status(HttpStatus.BAD_REQUEST).build()); 
 } 
 
 @PutMapping("/atualizar") 
 public ResponseEntity<Usuario> putUsuario( 
 @Valid @RequestBody Usuario usuario){ 
 return service.atualizarUsuario(usuario) 
 .map(resp -> ResponseEntity.status(HttpStatus.OK).body(resp)) 
 .orElse(ResponseEntity.status(HttpStatus.NOT_FOUND).build()); 
 } 
 
} 
Observe que nos Métodos Cadastrar, Atualizar e Auten�car, ao invés de usarmos a
injeção de dependência da Interface UsuarioRepository, estamos u�lizando a injeção de
dependência da Classe de Serviço UsuarioService porquê os 3 Métodos foram
implementados nela.
ALERTA DE BSM: Mantenha a Atenção aos Detalhes, nos métodos
postUsuario e putUsuario para não esquecer a notação @Valid. Caso
ela não seja inserida, ao fornecer parâmetros inválidos, o servidor
retornará o HTTP Status 500, ao invés do HTTP Status 400.
Para concluir, não esqueça de Salvar o código (File 🡪 Save All).
 Código fonte: Classe UsuarioController
👣 Passo 04 - Testar o Recurso Usuario no Postman
Vamos criar no Postman todas as requisições necessárias para testar os 5 Métodos do
Recurso Usuario. Veja abaixo como ficam as requisições para testar o Recurso Usuario:
DICA: Caso você tenha alguma dúvida sobre como criar as Requisições,
consulte a Documentação dos Recursos Postagem e Tema.
ATENÇÃO: Depois de criar o Relacionamento entre Classes, todas as Consultas
dos Recursos Postagem, Tema e Usuario trarão os Objetos associados.
4.1. Criando a Pasta Usuario
Vamos criar dentro da Collec�on Blog Pessoal a Pasta Usuario, que guardará todas as
requisições do Recurso Usuario.
1. Na Collec�on Blog Pessoal, clique nos 3 pon�nhos ao lado do nome da
Collec�on, para abrir o menu e clique na opção Add Folder.
2. Na janela que será aberta, informe o nome da pasta (Usuario) e pressione a tecla 
(Enter) para concluir.
https://github.com/conteudoGeneration/blog-pessoal/blob/17-Blog-(Security_UserController)/blogpessoal/src/main/java/com/generation/blogpessoal/controller/UsuarioController.java
4.2. Criando a Request - Cadastrar Usuario
Vamos começar pela requisição Cadastrar Usuario porquê sem um usuário cadastrado
não será possível auten�car (logar) no sistema e acessar os demais endpoints.
1. Na Pasta Usuario, clique nos 3 pon�nhos ao lado do nome da pasta, para abrir o
menu e clique na opção Add Request.
2. Configure a requisição conforme a imagem abaixo:
3. Observe que na requisição do �po Post o Corpo da requisição (Request Body),
deve ser preenchido com um JSON contendo o nome, o usuario(e-mail), a senha e
a foto(link), que vc deseja persis�r no Banco de dados.
4. Observe que depois de persis�r os dados do usuario, a aplicação retornará a
senha criptografada.
4.3. Criando a Request - Auten�car Usuario (Logar)
Usuário persis�do, agora vamos efetuar o login no sistema, que nos retornará o Token
de Autorização, que nos permi�rá consumir os demais endpoints e recursos da
aplicação.
1. Na Pasta Usuario, clique nos 3 pon�nhos ao lado do nome da pasta, para abrir o
menu e clique na opção Add Request.
2. Configure a requisição conforme a imagem abaixo:
3. Observe que no JSON estamos passando apenas o usuário e a senha, porquê são
as únicas informações que u�lizaremos no login. A Classe UsuarioLogin possui
outros atributos que serão preenchidos pela aplicação (se o login for efetuado
com sucesso) e retornados no JSON da resposta, como vemos na figura abaixo:
4. Observe que o Token foi gerado e enviado na resposta. Copie o Token da resposta
porquê vamos precisar dele nas próximas requisições.
5. Caso o login falhe, você receberá o status 401 (Unauthorized).
4.4. Criando a Request - Consultar todos os Usuarios - findAll()
1. Na Pasta Usuario, clique nos 3 pon�nhos ao lado do nome da pasta, para abrir o
menu e clique na opção Add Request.
2. Configure a requisição conforme a imagem abaixo:
3. Como a segurança foi habilitada, caso você envie a requisição do jeito que está,
você receberá o status 401 (Unauthorized), como mostra a figura abaixo:
4. A explicação é simples: Você precisa passar no cabeçalho da requisição o Token
recebido no login.
5. Clique na opção Headers e adicione a linha Authoriza�on. Na coluna Value da
linha insira o Token que você recebeu no Login, como mostra a figura abaixo:
6. Agora a sua requisição funcionará!
ALERTA DE BSM: Mantenha a Atenção aos Detalhes! Você deverá
inserir o token no cabeçalho de todas requisições dos Recursos
Postagem e Tema, caso contrário você receberá o status 401
(Unauthorized) em todas elas. Caso você efetue login com outro
Usuário, o Token deve ser alterado.
4.5. Criando a Request - Consultar Usuario por ID - findById(id)
1. Na Pasta Usuario, clique nos 3 pon�nhos ao lado do nome da pasta, para abrir o
menu e clique na opção Add Request.
2. Configure a requisição conforme a imagem abaixo:
3. Clique na opção Headers e adicione a linha Authoriza�on. Na coluna Value da
linha insira o Token que você recebeu no Login, como mostra a figura abaixo:
4.6. Criando a Request - Atualizar Usuário
1. Na Pasta Usuario, clique nos 3 pon�nhos ao lado do nome da pasta, para abrir o
menu e clique na opção Add Request.
2. Configure a requisição conforme a imagem abaixo:
3. Observe que na requisição do �po Put o Corpo da requisição (Request Body), deve
ser preenchido com um JSON contendo o Id, o nome, o usuario(e-mail), a senha e
a foto(link) que vc deseja atualizar no Banco de dados.
4. Clique na opção Headers e adicione alinha Authoriza�on. Na coluna Value da
linha insira o Token que você recebeu no Login, como mostra a figura abaixo:
👣 Passo 05 - Atualizar as Requisições Cadastrar e
Atualizar Postagem no Postman
Como habilitamos o Relacionamento entre as Classes Postagem e Usuario, para
Cadastrarmos e Alterarmos as Postagens vamos precisar atender alguns requisitos:
O Tema e o Usuario devem ser persis�dos antes de criar a nova Postagem.
Na requisição Cadastrar e Atualizar Postagem, o JSON enviado no Corpo da
Requisição deve conter um Objeto da Classe Tema iden�ficado apenas pelo
Atributo id e um Objeto da Classe Usuario iden�ficado apenas pelo Atributo id.
5.1. Atualização - Requisição Cadastrar Postagem
Vamos alterar o Corpo da requisição (Body), conforme a imagem abaixo:
No item marcado em vermelho na imagem acima, observe que está sendo passado
dentro do JSON um Objeto da Classe Usuario chamado usuario, iden�ficado apenas
pelo Atributo id.
Não esqueça de inserir o token no cabeçalho da requisição.
ATENÇÃO: O Objeto Usuario deve ser persis�do no Banco de dados antes
de ser inserido no JSON da requisição Cadastrar Postagem.
5.2. Atualização - Requisição Atualizar Postagem
Vamos alterar o Corpo da requisição (Body), conforme a imagem abaixo:
No item marcado em vermelho na imagem acima, observe que está sendo passado
dentro do JSON um Objeto da Classe Usuario chamado usuario, iden�ficado apenas
pelo Atributo id.
Não esqueça de inserir o token no cabeçalho da requisição.
ATENÇÃO: O Objeto Usuario deve ser persis�do no Banco de dados antes
de ser inserido no JSON da requisição Atualizar Postagem.
DESAFIO: O que acontecerá se você inserir no JSON das requisições
Cadastrar e Atualizar Postagem, no Objeto da Classe Usuario chamado
usuario, um id que não existe? Insira no Atributo id, do Objeto Usuario, um
id como 100, por exemplo, e veja o que acontece.
👣 Passo 06 - Atualizar os Métodos post e put na Classe
PostagemController
Se você fez o desafio acima, percebeu que estas implementações não conseguem checar
se o Objeto da Classe Usuario existe, logo se você inserir um Objeto que não existe (um
Id que não existe no Banco de dados), devido ao Relacionamento entre as Classes, será
retornado o HTTP Status 500 - Internal Server Error.
Para evitar este erro, faremos alguns ajustes na Classe PostagemController.
6.1. Inserir uma Injeção de Dependência da Classe Usuario na Classe
PostagemController
Linhas 44 e 45: Para termos acesso aos Métodos das Classes Usuario e
UsuarioController, precisamos inserir uma uma Injeção de Dependência da Classe
Usuario, logo abaixo da Injeção de Dependência da Classe Tema.
6.2. Atualização do Método post da Classe PostagemController
Linha 67: Através do Método existsById(Long id), da Interface UsuarioRepository
(Herança da Interface JPA), checamos se o id passado no Objeto usuario, da Classe
Usuario, inserido no Objeto postagem, da Classe Postagem, existe, assim como fizemos
na checagem da Classe Tema. Se ambos os Objetos exis�rem, a nova postagem será
persis�da no Banco de dados.
Para obter o id do usuario, u�lizamos os Métodos get das 2 Classes:
postagem.getUsuario().getId()
 Documentação: existsById()
6.3. Atualização do Método post da Classe PostagemController
Linha 80: Através do Método existsById(Long id), da Interface UsuarioRepository
(Herança da Interface JPA), checamos se o id passado no Objeto usuario, da Classe
Usuario, inserido no Objeto postagem, da Classe Postagem, existe, assim como fizemos
na checagem da Classe Tema. Se ambos os Objetos exis�rem, a nova postagem será
persis�da no Banco de dados.
Para obter o id do usuario, u�lizamos os Métodos get das 2 Classes:
postagem.getUsuario().getId()
 Código fonte do projeto 
Segurança do Blog Pessoal finalizada!!!
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html#existsById-ID-
https://github.com/conteudoGeneration/blog-pessoal/tree/17-Blog-(Security_UserController)

Outros materiais