0% acharam este documento útil (0 voto)
1 visualizações121 páginas

SpringBoot REST v2

O documento apresenta um guia para o desenvolvimento de sistemas web utilizando Spring Boot, focando em webservices REST. Inclui a definição de um gerenciador de dados pessoais com funcionalidades como listagem, inclusão, alteração e exclusão de dados, além de detalhar a arquitetura MVC e a injeção de dependências. Também aborda conceitos de REST, suas características e ferramentas para implementação em Java.

Enviado por

marcelloe537
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
1 visualizações121 páginas

SpringBoot REST v2

O documento apresenta um guia para o desenvolvimento de sistemas web utilizando Spring Boot, focando em webservices REST. Inclui a definição de um gerenciador de dados pessoais com funcionalidades como listagem, inclusão, alteração e exclusão de dados, além de detalhar a arquitetura MVC e a injeção de dependências. Também aborda conceitos de REST, suas características e ferramentas para implementação em Java.

Enviado por

marcelloe537
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

Desenvolvimento de

Sistemas Web

Desenvolvimento Backend com Spring Boot –


Webservices REST

Versão 25.2.0

Prof. Fernando Tsuda


Exemplo a ser desenvolvido
Gerenciador de dados pessoais
• Possibilitar a apresentação das • Internamente, deve manter as
seguintes informações: seguintes informações
• Nome completo adicionais:
• Data de nascimento • Apelido único (username)
• E-mail • Senha de acesso
• Telefone
• Interesses (selecionar entre
opções pré-cadastradas)
• Foto
• Link para Linkedin
• Link para Github
Prof. Fernando Tsuda
Exemplo a ser desenvolvido
Gerenciador de dados pessoais
• Funcionalidades previstas
• Listagem de pessoas
• Busca textual
• Visualizar dados da pessoa
• Inclusão de nova pessoa
• Upload da foto
• Alteração dos dados da pessoa
• Exclusão da pessoa
• Listagem de interesses

Prof. Fernando Tsuda


Definição das URIs + Códigos de resposta usuais
Ação Método HTTP + URI Códigos de resposta
Listar GET /recursos 200 – Sucesso + Array com dados
(se não existir, retornar Array vazio)
Incluir novo POST /recursos 201 – Incluído com sucesso + location (URI)
400 – Erro nos dados enviados (validação)
Visualizar 1 recurso GET /recursos/{id} 200 – Sucesso + Dados
existente 404 – Item não encontrado
Alterar existente PUT /recursos/{id} 200 ou 204 – Alterado com sucesso
404 – Item não encontrado
400 – Erro nos dados enviados (validação)
Excluir DELETE /recursos/{id} 200 ou 204 – Excluído com sucesso
404 – Item não encontrado
Nome do recurso na URI
- Usar nome no plural
- Usar letras minúsculas
- Se for composto, separar com hífen
(ex: dados-pessoais) Prof. Fernando Tsuda
Objetivos
• Apresentar os principais componentes para desenvolvimento de sistemas
web usando o Spring Boot (Webservices REST)
• Controllers
• Tratamento de requisições GET
• Resolução de URLs, envio de parâmetros, tratamento de cabeçalhos
• Envio de dados com POST
• Criação de funcionalidades com PUT e DELETE
• CORS
• Validação de dados
• Internacionalização das mensagens (i18n)
• Upload de arquivos
• Outros assuntos até o final do semestre
• Integração com banco de dados usando JPA (slides a parte)
• Inclusão de autenticação/autorização de acesso com Spring Security e JWT

Prof. Fernando Tsuda


Troca de mensagens
Modelo Client-Server usando protocolo
HTTP

HTML
Spring Boot
CSS Java
JS
Framework
• Conjunto de componentes e processos que visam facilitar o
desenvolvimento de um software específico, através de
funcionalidades que são comuns a várias aplicações
• Adoção implícita de boas práticas

Prof. Fernando Tsuda


Analogia:
Preparar uma
pizza

Prof. Fernando Tsuda


Spring Framework
• Framework que provê uma infraestrutura de componentes para o
desenvolvimento de aplicações Java
• Tem como principal característica a criação e o gerenciamento dos
objetos usados pela aplicação – estes objetos são chamados "Beans"
• Os beans são associados uns aos outros usando a técnica de Inversão
de controle (IoC - Inversion of control) ou Injeção de Dependências
(DI - Dependency Injection)
• Permite um desacoplamento entre os diversos módulos do sistema

Prof. Fernando Tsuda


Bean
• Objeto criado e gerenciado pelo Spring Framework
• Normalmente criado através do uso das anotações @Component ou
equivalente no nível das classes e @Bean para métodos que criam
objetos

Prof. Fernando Tsuda


Beans - Exemplos
@Component // Classe normal, sem recursos do Spring
public class ExemploComponent { public class ExemploBean {
// Spring Framework cria objeto }
// bean a partir desta classe
// no processo de Component Scan @Configuration
public class Inicializador {
}
// Spring cria objeto bean através da
Após a criação dos objetos, eles ficam // chamada ao método abaixo
@Bean
disponíveis para serem injetadas em
public ExemploBean exemploBean() {
outras classes. return new ExemploBean();
}
Também podem ser acessadas através do }
ApplicationContext

Prof. Fernando Tsuda


Bean - Tipos
Tipo Características Depende de
ambiente web
Singleton Uma instância única por aplicação. Configuração padrão. NÃO
Prototype Cada acesso gera um novo objeto. NÃO
Request Bean criado e mantido durante o processamento de uma SIM
requisição
Session Bean criado e mantido para cada sessão de usuário SIM
Application Bean criado por aplicação rodando dentro de um contexto web SIM
Websocket Bean criado e mantido durante uma sessão acessada via SIM
websocket

Prof. Fernando Tsuda


Exemplo Injeção Dependências
Modo usual – SEM injeção
public class SomeService { Neste exemplo, ao criar objetos com new
... SomeService(), pode ocorrer uma situação onde
terão 2 objetos deste tipo instanciados ao
}
mesmo tempo (um pela Teste1, outro pela
Teste2)
public class Teste1 {
private SomeService serv = new SomeService();
}

public class Teste2 {


private SomeService serv = new SomeService();
}

Prof. Fernando Tsuda


Exemplo Injeção Dependências
Uso do @Autowired @Component
public class SomeService {
...
O uso da anotação @Component nas classes
}
permite que o Spring crie e gerencie as
instâncias de cada uma delas. Por padrão, é @Component
adotado o padrão "Singleton" (somente 1 public class Teste1 {
instância/objeto é criada por classe).
@Autowired
Através do uso do @Autowired nas classes
Teste1 e Teste2, o Spring sabe que o "serv" vai private SomeService serv;
manter uma associação com o objeto }
SomeService e "injeta" uma referência nestas
@Component
"variáveis".
public class Teste2 {
@Autowired
private SomeService serv;
}
Prof. Fernando Tsuda
Exemplo Injeção Dependências
Uso do @Autowired
@Component @Component
public class FooService { public class Teste {
...
}
@Autowired
@Component private FooService fooService;
public class BarService {
... @Autowired
} private BarService barService;

}
OBS: Uso do @Autowired não é
recomendado em projetos novos
– usar injeção via Contrutor ou
via método Set
Exemplo Injeção Dependências pelo
Construtor ou set()
@Component @Component
public class FooService { public class Teste {
...
private FooService fooService;
}
private BarService barService;
@Component
public class BarService {
@Autowired // <-- PODE SER OMITIDO SE TIVER SÓ 1 CONSTRUTOR.
...
public Teste(FooService fooService, BarService barService) {
}
[Link] = fooService;
[Link] = barService;
Injeção é tratada }
automaticamente pelo IoC do
}
Spring Framework através do
construtor ou set da classe Teste
Exemplo Injeção Dependências pelo
Construtor ou set()
@Component @Component
public class FooService { public class Teste {
...
private FooService fooService;
}
private BarService barService;
@Component
public class BarService {
@Autowired // <-- PODE SER OMITIDO SE TIVER SÓ 1 CONSTRUTOR.
...
public Teste(FooService fooService) {
}
[Link] = fooService;
}
Injeção é tratada // Abordagem do set indica que dependência é opcional
public void setBarService(BarService barService) {
automaticamente pelo IoC do [Link] = barService;
Spring Framework através do }
construtor ou set da classe Teste }
Exemplo Injeção Dependências pelo
Construtor com Lombok
@Component @Component
public class FooService { @RequiredArgsContructor // Lombok
... public class Teste {
}

@Component private final FooService fooService;


public class BarService { private final BarService barService;
...
} }
ATENÇÃO: Dependendo da IDE
usada, pode ser necessário instalar o
// Anotação @RequiredArgsConstructor do Lombok gera Lombok como extensão ou plugin
// automaticamente o construtor abaixo: para este código funcionar
public Teste(FooService fooService, BarService barService) {
[Link] = fooService;
[Link] = barService;
}
Spring Framework
• Primeira versão lançada em 2003
• Criado e mantido pela Pivotal ([Link]
• Versão atual: 6.2.x
• 6.2.0 lançada em nov/2024
• Precisa rodar com Java 17 ou superior
• Não é compatível com namespace do Java EE (javax.*) – Somente Jakarta EE (jakarta.*)
• Versões anteriores
• 6.0.0 lançada em nov/2022

Prof. Fernando Tsuda


Spring Framework
• Composto por vários módulos com finalidades específicas
• Exemplos:
• Web
• Acesso aos dados

Prof. Fernando Tsuda


Arquitetura 3 camadas (layers)

Presentation Layer

Service Layer

Repository Layer

Prof. Fernando Tsuda


DTOs (Data Transfer Objects)
Representação das informações que
podem trafegar para acessos externos
Apresentação/ Interface
com "mundo externo"
Services/
Casos de uso
Services / Casos de
Repository
uso
Entities
Representação das
informações do banco
até a camada de Services

Prof. Fernando Tsuda


Modelo Client-Server com MVC

Model

View Controller
Arquitetura MVC
Consulta o Altera o
estado estado

Model

Notificação de
mudanças
Seleciona a view

View Controller
Gestos do usuário
Chamada de métodos
Eventos
Arquitetura MVC

Model View Controller

• Encapsula o estado • Renderiza o modelo • Define o


da aplicação • Requisita as comportamento da
• Responde às atualizações do aplicação
consultas ao estado modelo • Mapeia as ações do
• Expõe as • Envia os gestos dos usuário ao modelo
funcionalidades da usuários ao Controle • Seleciona as views de
aplicação • Permite ao Controle resposta
• Notifica as Views selecionar a View • Um controle para
sobre mudanças cada funcionalidade
Vantagens MVC
• Desacoplamento entre a apresentação, controle, comportamento e
persistência de dados, possibilitando uma maior flexibilidade
• Facilita a manutenção e evolução do projeto, ao reduzir a
complexidade do código
• Promove a divisão de responsabilidades
Spring Web MVC
• Módulo do Spring Framework que possibilita o desenvolvimento de
aplicações web que usem a arquitetura MVC (Model-View-Controller)
• Utiliza o modelo de processamento action-based (ou push-based),
onde os controladores irão ser acionados através da requisição HTTP.
• Seu funcionamento se baseia em um front controller (ou dispatcher
servlet), responsável pelo recebimento das requisições e posterior
encaminhamento ao bean correspondente.

Prof. Fernando Tsuda


Spring MVC X Servlet/JSP
Model View Controller Passagem de
informações do
Controller para View
Servlet/JSP em JSP Servlet [Link]()
conjunto no modelo
MVC
Spring MVC + Requisitos de Templates HTML Classe Java [Link]()
Thymeleaf (web negócio com sintaxe configurada como OU
tradicional) implementados com Thymeleaf @Controller [Link]()

Spring MVC linguagem Java Aplicação Javascript Classe Java Não se aplica
(Webservices REST rodando no cliente configurada como (Serialização JSON)
– web moderna) + integração via @RestController
JSON

Prof. Fernando Tsuda


MVC com Servlets/JSP e JEE
Model 2 Architecture

Server
Spring Web MVC (Tradicional)
HTTP

MODEL

Prof. Fernando Tsuda


Spring Web MVC (Tradicional)
Implementado através
do HttpServlet
1) Requisição é recebida
HTTP
pelo Front controller (ou
Dispatcher Servlet)

MODEL

Prof. Fernando Tsuda


Spring Web MVC (Tradicional)
2) O Front controller delega o
processamento para o
Controller correspondente

HTTP

MODEL

Prof. Fernando Tsuda


3) Controller processa a
Spring Web MVC (Tradicional) requisição e retorna um
modelo e instruções sobre o
template a ser usado para
gerar a resposta
HTTP

MODEL

Prof. Fernando Tsuda


Spring Web MVC (Tradicional)
HTTP

MODEL

4) Front controller repassa o


modelo para o template, que
irá gerar a resposta ao cliente

Prof. Fernando Tsuda


Spring Web MVC (Tradicional)
HTTP

MODEL

5) Após a resposta ser


gerada, Front controller
retorna a resposta ao cliente

Prof. Fernando Tsuda


Spring Web MVC (Tradicional) Implementado pelo
desenvolvedor
Fornecido pelo
HTTP Spring MVC

MODEL

Objeto do Spring
usado para troca de
informações entre
Implementado pelo Controller e View
desenvolvedor

Prof. Fernando Tsuda


[Link]
Prof. Fernando Tsuda
Webservice
• Também conhecido como APIs Web
• Aplicação web disponibilizando informações para outras aplicações
clientes
• Sites (Interfaces frontend)
• Aplicativos móveis
• Sensores/atuadores IoT (Internet das coisas)
• Outras aplicações "client" com acesso à web
• Ex: Postman, cURL

Prof. Fernando Tsuda


REST
• REpresentational State Transfer (Transferência de estado
representacional).
• Estilo arquitetural de software que permite o acesso às informações
dos recursos centralizados em um ou mais servidores sem a
necessidade de manutenção de estado com o cliente consumidor.
• Informações são acessadas através de operações (ou métodos)
definidos pelo protocolo HTTP (Hypertext Transfer Protocol).

Prof. Fernando Tsuda


Características REST X HTTP
• Recursos são identificados/representados por URIs (Uniform Resource
Identifier) e são descritos usando uma notação comum (normalmente
JSON ou XML)
• Stateless (sem estado) → EVITAR USAR SESSÃO HTTP
• Usa os métodos do HTTP para definir as ações a serem realizadas
• GET – obtém um recurso do servidor
• POST – inclui um novo recurso no servidor
• PUT/PATCH – substituí um recurso inteiramente ou parcialmente, respectivamente
• DELETE – apaga um recurso
• Usa os códigos do HTTP para indicar o resultado da operação
• 200 – Sucesso
• 201 – Recurso criado
• 400 – Erro nas informações enviadas
• 404 – Recurso não encontrado
Prof. Fernando Tsuda
Ferramentas para implementar REST em Java
• Spring MVC
• Pode ser usado somente usando o módulo MVC ou através do módulo Spring
Data REST
• Permite uso do módulo Spring HATEOAS para criação de webservices RESTful
• Componente Jackson 2 é responsável pela Serialização/Deserialização de um
objeto Java para String JSON e vice-versa
• JAX-RS (parte do Jakarta EE) → Atualmente está na versão 2.x (a
partir do Java EE 7)
• Jersey
• RESTEasy
• Apache CXF
Jackson 2
• Componente padrão usado pelo Spring Boot para converter os
objetos Java (POJOs) em JSON e vice-versa, através do objeto
ObjectMapper
• Na configuração padrão, as seguintes propriedades do ObjectMapper
são desabilitadas na aplicação Spring Boot
• MapperFeature.DEFAULT_VIEW_INCLUSION
• DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
• SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
• SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS

[Link]

Prof. Fernando Tsuda


Jackson 2 - Exemplo de serialização
public class Produto {
private String nome;
private Integer preco;
ObjectMapper objectMapper = new ObjectMapper();
public Produto() { }
Produto prod = new Produto("Bolo", 100);
public Produto(String nome,
String json = [Link](prod);
int preco) {
[Link] = nome;
[Link] = preco;
}
// Getters e Setters
}

Prof. Fernando Tsuda


Jackson 2 - Exemplo de de-serialização
{
"nome": "Bolo",
"preco": 100
}
ObjectMapper objectMapper = new ObjectMapper();
String json = """
{
"nome": "Bolo",
"preco": 100
}
""";
Produto prod = [Link](json, [Link]);

Prof. Fernando Tsuda


Spring MVC Tradicional X REST
Model View Controller Passagem de Outras características
informações do
Controller para View
Spring MVC + • Templates HTML Classe Java [Link]() • Somente GET ou
Thymeleaf com sintaxe configurada OU POST
(web Thymeleaf como [Link]() • Sessão para manter
tradicional - • Telas geradas no
@Controller estado do usuário
SSR) servidor (SSR =
Server side
Requisitos de
rendering)
negócio
Spring MVC implementado • Aplicação Javascript Classe Java Não se aplica • Todos métodos HTTP
(Webservices rodando no cliente configurada (Serialização JSON) com semântica para
com linguagem
REST - web + integração via como ações
moderna - Java requisições @RestController
• Stateless (necessita
frontend assíncronas + JSON
"separado") • Processamento de adotar algum padrão
telas no navegador para manter dados
(cliente-side de navegação)
rendering)
Prof. Fernando Tsuda
Spring MVC Tradicional X REST
Vantagens Desvantagens

Spring MVC + Thymeleaf • Possibilita desenvolver exemplos mais • Essa abordagem de SSR está em desuso no
(web tradicional - SSR) didáticos e mais simples, pois envolve mercado, principalmente para aplicações
somente a lógica do backend + sintaxe voltadas para usuários em geral
do Thymeleaf para geração das telas
com resultados
• Na maioria dos casos, não necessita
conhecimentos de Javascript
Spring MVC (Webservices • Abordagem mais utilizada pelo mercado • Necessita conhecimento do Javascript para
REST - web moderna - atualmente manipulação da interface HTML e criação de
frontend "separado") • Facilita a adoção de frameworks e requisições assíncronas
bibliotecas para a criação de projetos de • Exemplos mais complexos, pois, para cada
frontend mais complexos (ex: React, funcionalidade, será necessário criar Javascript
Angular, VueJS) para receber e apresentar resultados na tela

Prof. Fernando Tsuda


CORS
• Cross-origin resource sharing
• Mecanismo que usa cabeçalhos HTTP adicionais para garantir
permissão de acesso a recursos de um servidor diferente do da
origem da página (domínio) em uso
• Um user-agent realiza um requisição HTTP de origem cruzada quando
executa uma requisição de um domínio, protocolo ou porta diferente
do qual originou o documento corrente.

[Link]
Prof. Fernando Tsuda
CORS - Exemplo
• Usuário acessando [Link]
• Javascript fazendo requisição para a URL [Link] deve
enviar um cabeçalho Origin indicando a URL de origem.
• Acesso ao recurso [Link] só será permitido se a resposta da
requisição apresentar cabeçalhos adicionais (ex: Access-Control-Allow-Origin)
• Se o cabeçalho adicional não estiver presente, o user-agent não permite a
execução do Javascript
• Configuração de CORS em aplicações Spring MVC
• Ver [Link]

Prof. Fernando Tsuda


RESTFul
HATEOAS →Hypermedia As The Engine Of Application State

[Link]
Características REST {
"account_number" : 123456,
"balance_value" : 100.0,
"balance_currency" : "USD",
"links" : [

• Hypermidia → Links para que o {


"rel" : "deposit",

recurso possa ser manipulado "type" : "PUT",


"href" : "[Link]
},
{
HTTP/1.1 200 OK "rel" : "withdraw",
"type" : "POST",
Content-Type: application/json "href" : "[Link]
Content-Length: ... },
{
"rel" : "transfer",
"type" : "POST",
"href" : "[Link]
},
{
"rel" : "close",
"type" : "POST",
"href" : "[Link]
}
]
}

Referência: [Link]
Desenvolvendo uma aplicação
REST com Spring MVC

Prof. Fernando Tsuda


Configuração inicial da aplicação
• 3 formas principais de configuração
1. Declarativa – configuração usando arquivos XML
2. Programática – configuração usando programação
3. Spring Boot – projeto que permite o desenvolvimento de aplicações
usando os componentes do Spring
• Vantagem do Spring Boot
• Inclui automaticamente no projeto configurações iniciais básicas para as
dependências adicionadas (projetos "starter")
• Ex: No starter web, o servidor Tomcat já é inicializado com configurações padrão
• Permite executar uma aplicação web a partir de um projeto Java comum
(projeto não-web) → Servidor web Tomcat embutido no projeto

Prof. Fernando Tsuda


Spring Framework/Boot – Pré-requisitos
• Maven ou Gradle
• Versionamento semântico (SemVer) e política de atualizações
• Orientação a objetos
• JavaBean/POJOs
• Convenção ao invés de configuração
• Configuração através de anotações
• Desacoplamento de componentes
• Interfaces
• Organização das URLs (ou URIs) da aplicação (sitemaps)
Prof. Fernando Tsuda
Versionamento semântico (SemVer)

1.2.3
Major – Versão principal do componente, sua mudança pode
envolver alterações que afetam o software desenvolvido que
usa o componente
Minor – Versão secundária do componente, sua mudança
pode trazer novas funcionalidades mas devem evitar impactar
o software desenvolvido

Patch – Versão que indica correções de bugs e pequenas


melhorias, sem trazer novas funcionalidades

Prof. Fernando Tsuda


Spring Boot
• Versão atual: 3.5.x
• Versão 3.5.0 lançada em mai/2025 → Usa Spring Framework 6.2.x
• Também precisa de Java 17 ou superior para funcionar
• Usa como base o Jakarta EE 9 mas suporta recursos do Jakarta EE 10
• Patches lançados mensalmente (aproximadamente)
• Versão “minor” lançada a cada 6 meses (aproximadamente)
• Versões anteriores
• 3.4.0 – lançada em nov/2024
• 3.3.0 – lançada em mai/2024
• 3.2.0 – lançada em nov/2023
• 3.1.0 – lançada em mai/2023
• 3.0.0 – lançada em nov/2022

Prof. Fernando Tsuda


Criar e abrir o projeto
Spring Boot – seguir [Link]
instruções conforme link
fornecido no Blackboard Group: [Link]
até 19:45 Artifact: exemplos-spring-inicial
Package name:
[Link]
Dependencies (Clicar em Add
Dependencies, digitar e
selecionar):
• Web
• Devtools
• Configuration Processor
• Validation
• Lombok
• Thymeleaf
- Clicar em Generate para baixar o
zip contendo o projeto
- Descompactar e abrir o projeto
na IDE de preferência
Spring Doc – Open API 3.0 + Swagger
• Incluir a dependência abaixo no [Link]
<dependency>
<groupId>[Link]</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.8.13</version>
</dependency>

• Após desenvolver RestControllers e rodar aplicação, acessar a


seguinte URL: [Link] para visualizar
documentação online das URIs (endpoints) disponíveis
• Site oficial da biblioteca: [Link]
Prof. Fernando Tsuda
Clients para testes de Webservices REST
• Postman
• Insomnia
• Bruno
• cURL

[Link]

Prof. Fernando Tsuda


Estrutura do projeto • Pacotes de códigos-fonte → Classes Java
• Pacotes de teste → Classes Java para testes
unitários
• Importante: neste exemplo, todas a classes
devem ficar dentro do pacote ou em
subpacotes de [Link]
• Outros códigos-fonte
• src/main/resources
• Arquivo [Link] → Propriedades
da aplicação
• static → Diretório onde deverão ser colocados
arquivos estáticos (html estático, css, js,
imagens, fontes, etc)
No Netbeans: • templates → Diretório onde deverão ser
colocados arquivos usados como templates para
Projeto Java geração da view (JSPs, html dinâmico)
NORMAL
(NÃO WEB)
• Arquivos do projeto
• [Link] → Configurações do projeto Maven

Prof. Fernando Tsuda


IMPORTANTE!!!
• Notar que o projeto gerado será empacotado como um arquivo JAR, pois o
Spring Boot irá usar uma versão incorporada (embedded) do Web
container Tomcat.
• Apesar de ser empacotado como um arquivo JAR, o sistema irá se
comportar normalmente como um sistema web.
• O acesso à aplicação deve ser feito através do navegador usando, por
padrão, a URL [Link] - ou seja, a aplicação roda usando
contexto raiz (root context-path) (/).
• Para alterar porta e contexto-path, incluir as seguintes configurações no arquivo
[Link] (fornecido no projeto inicial)
[Link]=8080
[Link]-path=/
• Antes de reexecutar a aplicação, lembrar de parar a execução anterior. A
dependência DevTools permite que as atualizações no código sejam feitas
sem necessidade de reiniciar a aplicação na maioria das vezes – basta fazer
as alterações, salvar e acessar o navegador
Prof. Fernando Tsuda
Classe principal (gerada automaticamente)
Notar a anotação @SpringBootApplication,
responsável por aplicar as configurações padrão para
que o aplicativo funcione como um aplicativo web
MVC
@SpringBootApplication
public class ExemploApplication {

public static void main(String[] args) {


[Link]([Link], args);
}
}
A anotação @SpringBootApplication equivale às seguintes anotações:
@Configuration
@ComponentScan
@EnableAutoConfiguration

Prof. Fernando Tsuda


Anotações básicas
• @Configuration – Indica que a classe representa uma configuração da
aplicação. Dentro desta classe podem ser criados métodos com a
annotation @Bean, cujo resultado fica disponível para ser injetado
dentro da aplicação Spring através do applicationContext.
• @ComponentScan – Indica que o Spring irá procurar as classes de
configuração, @Components e derivados dentro do package e
subpackages onde a classe anotada se encontra.
• @EnableAutoConfiguration – Ativa o recurso de auto configuração
dos módulos do Spring Boot

Prof. Fernando Tsuda


Anotações comuns da web
• @Controller – Indica que a classe irá ser configurada como um
Controlador web dentro de uma aplicação Spring MVC
• @RequestMapping – Mapeia um padrão de URL (rota) para a
requisição ser processada pela classe e/ou pelo método
• Forma reduzida (neste exemplo aceita requisição de qualquer método HTTP):
@RequestMapping("/exemplo") OU @RequestMapping(value="/exemplo")
• Forma completa:
@RequestMapping(value="/exemplo", method=[Link])
OU
@RequestMapping(path="/exemplo", method=[Link])

Prof. Fernando Tsuda


Anotações comuns
• @GetMapping – Atalho do mapeamento de um padrão de URL. Para
processamento de requisições GET. Equivale ao @RequestMapping
com method configurado como [Link].
• @PostMapping – Atalho do mapeamento de um padrão de URL para
processamento de requisições POST. Equivale ao @RequestMapping
com method configurado como [Link].

• Pela mesma lógica, também podem ser usadas as anotações


@PutMapping, @PatchMapping, @DeleteMapping e outros
métodos HTTP usuais
Prof. Fernando Tsuda
Anotações comuns
• @ResponseBody – Configuração que indica que a resposta do
método deverá ser retornada como corpo da mensagem de resposta
HTTP
• O uso da anotação @RestController ao invés do @Controller antes da
declaração da classe possibilita a omissão desta anotação nos métodos
• Caso não seja informada, o Spring MVC irá tratar a resposta do método do
tipo String como sendo a view que será utilizada no fluxo MVC tradicional.

Prof. Fernando Tsuda


Diferenças @Controller X @RestController
para retornar Body HTTP
@Controller @RestController
public class TesteController1 { public class TesteController2 {

@GetMapping("/teste1") @GetMapping("/teste2")
@ResponseBody // Não precisa do @ResponseBody
public String mostrarMensagem() { public String mostrarMensagem() {
return "Exemplo @Controller"; return "Exemplo @RestController";
} }
} }
ATENÇÃO: Neste caso acima, a não inclusão do
@ResponseBody indica ao Spring que a String
retornada representa o nome da
view/template que irá gerar a resposta ao
usuário (modelo MVC tradicional)

Prof. Fernando Tsuda


Controller com parâmetros – Usando
@RequestParam
@GetMapping("/exemplo-request-param")
public Dados exemploRequestParam (
@RequestParam("param1") String param1,
@RequestParam(name = "param2str", required = true,
defaultValue = "xyz") String param2,
@RequestParam(name = "param3int", required = false,
defaultValue = "99") int param3) {
Dados dados = new Dados(param1, param2, param3);
return dados;
}
Parâmetros enviados através de query string
Ex: [Link]

Prof. Fernando Tsuda


Controller com parâmetros – Usando
@PathVariable
@GetMapping("/exemplo-path-var/{param1str}/{param2int}")
public Dados exemploPathVariable(
@PathVariable("param1str") String param1,
@PathVariable(name = "param2int",
required = true) int param2) {
Dados dados = new Dados(param1, param2);
return dados;
}

Parâmetros enviados no caminho da URL


Ex: [Link]

Prof. Fernando Tsuda


POST – Objetivos do exemplo
• Cadastrar as seguintes informações:
• Nome (obrigatório, máx. 100 caracteres)
• Apelido (obrigatório, máx. 64 caracteres)
• E-mail (obrigatório, máx. 100 caracteres e formato válido)
• Telefone
• Data de nascimento (obrigatório, data no passado)
• Senha / Repetição senha (obrigatórios)
• Interesses (Tecnologia / Esportes / Gastronomia / Viagens / Investimentos) →
Múltiplas opções pré cadastradas

Prof. Fernando Tsuda


Pontos importantes ao implementar POST
• Modelar uma classe POJO/DTO que represente as informações que
serão preenchidas no formulário
• POJO (Plain Old Java Object)→ Classe Java com atributos privados, acesso via
get/set e construtor "padrão" (sem parâmetros)
• Usualmente, os atributos name definidos nas tags
<input>/<textarea>/<select> serão os mesmos atributos da classe criada
• No método que trata a requisição POST (definido pela anotação
@PostMapping), incluir a anotação @RequestBody no parâmetro que
recebe o objeto com as informações preenchidas

Prof. Fernando Tsuda


POST básico
@PostMapping
public ResponseEntity<Void> salvar(@RequestBody Dados dados) {

// *** IMPLEMENTAR A LÓGICA PARA TRATAR OS DADOS RECEBIDOS ***

// Prepara a URI que identifica os dados salvos


// Essa informação é retornada no cabeçalho "Location"
URI location =
[Link]().path("/{id}")
.buildAndExpand([Link]()).toUri();
return [Link](location).build();
}

Prof. Fernando Tsuda


Validação de dados
• Client-side
• Uso de atributos dos campos input (required, max, min, pattern, uso dos types email, number etc)
• Funções de validação Javascript para lógicas complexas que envolvam mais de um campo
• Referência MDN: [Link]
• Server-side
• Jakarta/Java EE – Bean Validation 2.0 (JSR-380)
• @NotNull
• @NotBlank
• @Min(<valor>)
• @Max(<valor>)
• @Size(min = <valor>, max = <valor>)
• @Future
• @Past
• @Digits(integer = <valor>, decimal = <valor>
• @Pattern(<regex>)
• @Email
[Link]
[Link]
Prof. Fernando Tsuda
Validação de dados
• A partir do Spring Boot 2.3.x, o módulo de validação deve ser
declarado de maneira explícita como uma dependência no [Link]
• Caso o módulo não tenha sido incluído ao criar o projeto no Spring
Initializr, adicionar o trecho abaixo no [Link]

<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Prof. Fernando Tsuda


Validação de dados
• Na classe POJO/DTO/Entity
• Usar as anotações do Bean Validation nos atributos que devem ser validados
• No RestController
• Adicionar a anotação @Valid no objeto que está sendo recebido do cliente via
@RequestBody
• Na view (Javascript)
• Em caso de erros, o Servidor irá retornar o status 400 – Bad request
• Analisar o objeto de erro retornado no corpo da mensagem
• Notar a presença de um Array "errors", onde cada erro contém as propriedades "field" e
"defaultMessage"
• Usar estas e outras informações no código Javascript para apresentar as informações na
tela (seletor CSS no [Link]() e texto da mensagem)

Prof. Fernando Tsuda


POST com validação

@PostMapping("/salvar")
public DadosPessoais salvar(@RequestBody @Valid DadosPessoais dadosEnviados) {
[Link]([Link](), dadosEnviados);
return dadosEnviados;
}

Prof. Fernando Tsuda


Upload de arquivos
• O upload em um sistema web é essencialmente o envio de um
arquivo local da máquina (através do navegador) para o servidor
remoto.
• Usualmente, o arquivo deverá ser acessado remotamente pela web.
Para isso, é necessário configurar uma URL que mapeie o local onde
os arquivos foram salvos no servidor.

Prof. Fernando Tsuda


Upload de arquivos
Implementação do upload via web:
• No código HTML do formulário que irá enviar o arquivo:
• Configurar o atributo “enctype” com o valor "multipart/form-data" no <form>
• Incluir um ou mais <input type="file" name="nome-campo">
• OU implementar Javascript que recebe a imagem via FormData e enviar
requisição usando Fetch API
• No Controller, receber o arquivo através do parâmetro
@RequestParam("nome-campo") MultipartFile arquivo
• A lógica na aplicação servidora consiste em copiar o conteúdo do
arquivo recebido pela rede para o destino (disco, banco de dados,
etc).
Prof. Fernando Tsuda
ATENÇÃO
• No processamento do upload, EVITAR salvar os arquivos nos
diretórios do projeto
• Esse diretório só vai existir na máquina do desenvolvedor
• Arquivos não serão mantidos quando a aplicação for implantada/atualizada
em algum servidor
• Criar um diretório externo separado do projeto para manter as
imagens

Prof. Fernando Tsuda


Upload de arquivos
• Formulário HTML para envio (com Javascript/Fetch API/FormData)
<script>
<form id="formUpload"> async function upload(event) {
<div> [Link]();
<label>Selecione o arquivo</label> const formData = new FormData([Link]);
<input type="file" name="arquivo" /> // [Link] acima equivale a
</div> // [Link]('formUpload')
<button type="submit">Enviar</button> const httpResp = await fetch('/upload', {
</form> method: 'POST',
body: formData,
});
if ([Link]) {
alert('Arquivo enviado com sucesso!');
} else {
Cabeçalho content-type: alert('Erro ao enviar o arquivo.');
multipart/form-data está implícito no }
objeto formData }
[Link]('formUpload')
.addEventListener('submit', upload);
</script>
Prof. Fernando Tsuda
Upload de arquivos
• Controller responsável por receber o arquivo e gravar em disco
@RestController
public class UploadController {

@PostMapping("/upload")
public ResponseEntity<?> receberArquivo(@RequestParam MultipartFile arquivo) {
Path destino = [Link]("C:/uploads", [Link]());
try {
[Link]([Link](), destino, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
[Link]();
return [Link]().body("Erro - Arquivo já existe");
}
return [Link]().build();
}

Prof. Fernando Tsuda


Upload de arquivos
Caminho para acessar os arquivos após upload
• Configurar uma rota para acessar os arquivos que estão no diretório
de destino na classe de configuração do Spring MVC.
• Criar a classe WebMvcConfig caso não exista
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
[Link]("/arquivos-uploads/**")
.addResourceLocations("[Link]
}
}

Prof. Fernando Tsuda


Internacionalização (i18n)
• Técnica que permite preparar a aplicação para suportar mensagens
em diversos idiomas
• Navegador envia o código do idioma no cabeçalho HTTP Accept-Language
• Referências:
• [Link]
• [Link]
• [Link]

Prof. Fernando Tsuda


Internacionalização (i18n)
• Criar os arquivos com as mensagens nos idiomas suportados. Por
padrão do Spring Boot, o nome do arquivo deve iniciar com
"messages" e completado com o código da localidade (idioma, país →
Exemplos: Brasil = pt_BR, Idioma inglês = en)

# Arquivo /src/main/resources/messages_pt_BR.properties
# Mensagens em português/Brasil
[Link]-vindas=Bem vindo
[Link]-com-parametro=Olá {0}

# Arquivo /src/main/resources/messages_en.properties
# Mensagens em inglês
[Link]-vindas=Welcome
[Link]-com-parametro=Hello {0}

Prof. Fernando Tsuda


Internacionalização (i18n)
• Acessar as mensagens usando o comando [Link]()

@RestController
public class ExemploController {

@Autowired
private MessageSource messageSource;

@GetMapping("/boas-vindas")
public String boasVindas() {
return [Link]("[Link]-vindas", [Link]());
}

// Acessar [Link]
@GetMapping("/ola")
public String ola(@RequestParam("nome") String nome) {
return [Link]("[Link]-com-parametro",
new String[] { nome }, [Link]());
}
}
Prof. Fernando Tsuda
Internacionalização (i18n)
• Para integrar as mensagens com o mecanismo de validação, tem que
implementar manualmente uma configuração para associar o
resource bundle ao mecanismo de validação
• Caso não exista, criar a classe WebMvcConfig e incluir a lógica abaixo
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

@Bean
public LocalValidatorFactoryBean getValidator(
@Autowired MessageSource messageSource) {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
[Link](messageSource);
return bean;
}

}
Prof. Fernando Tsuda
Internacionalização (i18n)
• Nas anotações de validação, usar a expressão {<chave-mensagem>}
para indicar qual mensagem será apresentada
public DadosDto {

@NotBlank(message = "{[Link]}")
private String mensagem;
}

• Nos arquivos de mensagens, incluir, por exemplo, a propriedade


abaixo para cada idioma, traduzindo o texto
[Link]=A mensagem não pode ser nula nem ter somente espaços

Prof. Fernando Tsuda


Outros tópicos Spring Boot para ver
• Tratamento global de erros
(@ControllerAdvice/@RestControllerAdvice, @ExceptionHandler)
• Eventos da aplicação (@EventListener)
• Tarefas periódicas (@Scheduled)
• Uso de profiles
• Spring Boot Actuator

• Outras dicas em [Link]


desenvolvimento/blob/main/[Link]
Prof. Fernando Tsuda
Integração com DB usando Spring Data JPA
• ORM → JPA
• Atividades:
• Criação do banco de dados
• Configuração da aplicação para integração com o BD (ex: MySQL, H2, etc)
• Configuração das classes e atributos usando anotações do JPA
• @Entity, @Id, @Column
• Anotações do Bean Validation podem ser usadas para criar restrições no banco de dados
(ex: campos not null, tamanho dos campos, etc)
• @OneToOne, @OneToMany/@ManyToOne e @ManyToMany → Usadas para mapear
relacionamentos entre entidades distintas
• Configuração e implementação das funcionalidades nos componentes
@Repository

Prof. Fernando Tsuda


Autenticação e autorização
• Autenticação – Identificar o usuário que acessa a aplicação. Saber
QUEM está acessando o sistema.
• Autenticação é feito através do Login (normalmente usando credenciais do
tipo identificação + senha)
• Manter informações do usuário autenticado em Sessão (sistemas
tradicionais) ou em Tokens (webservices)
• Mecanismo de autorização – Saber O QUE o usuário pode acessar
• Controlado através das Permissões/Papeis atribuídos ao usuário
Autenticação e autorização de acesso com
Spring Security
• Módulo do Spring responsável pelas funcionalidades relacionadas a
segurança de uma aplicação
• Implementar autenticação/autorização através das seguintes atividades
• Adicionar dependência do Spring Boot Security Starter no [Link]
• Desenvolver classe Permissao implementando a interface GrantedAuthority
• Desenvolver classe UsuarioSistema implementando a interface UserDetails
• Desenvolver classe de serviço UsuarioSistemaService implementando
UserDetailsService (método loadUserByUsername(String username))
• Criar classe de configuração SecurityConfig para permitir a associação dos padrões
de URL com os papeis definidos pela classe Permissao.
• Adicionar Beans PasswordEncoder e AuthenticationManager
• Criar @RestController de Login (+ desabilitar Form Login padrão do Spring Security)
• Verificar formato de configuração pós Spring Security 5.7/Spring Boot 2.7 (Beans de
configuração + Uso de funções Lambda DSL no método filterChain)

Prof. Fernando Tsuda


Filter chain

[Link]

Prof. Fernando Tsuda


Prof. Fernando Tsuda
Se estiver criando projeto novo em
[Link], pode-se adicionar a
Dependência [Link] dependência “security” na seção
correspondente.
<!-- SPRING SECURITY STARTER PADRÃO-->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- PARA USAR JWT, ADICIONAR A DEPENDÊNCIA ABAIXO -->


<!-- JA INCLUI O STARTER PADRÃO ACIMA -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

Prof. Fernando Tsuda


Spring Security Starter
• A configuração padrão do Spring Security Starter apresenta as
seguintes características
• Usuário padrão "user"
• Senha gerada aleatoriamente na inicialização da aplicação (apresentada no
log)
• Proteção de acesso para todas as URLs (rotas) da aplicação
• Telas para login e funcionalidade de logout

[Link]

Prof. Fernando Tsuda


Modelo genérico para associar Usuários X
Permissões
Classe Permissao
public class Permissao implements GrantedAuthority {

@Override
public String getAuthority() { return nome; }

OBS: A String retornada pelo método sempre deve ter


o prefixo “ROLE_” (ex: ROLE_ADMIN,
ROLE_FUNCIONARIO, ROLE_GERENTE)

Prof. Fernando Tsuda


Classe UsuarioSistema
public class UsuarioSistema implements UserDetails {

@Override
public String getUsername() { return username; }

@Override
public String getPassword() { return hashSenha; }

@Override
//public Collection<? extends GrantedAuthority> getAuthorities() {
public List<Permissao> getAuthorities() { return permissoes; }

// Opcional - IMPLEMENTAR DEMAIS MÉTODOS DE UserDetails


}
Prof. Fernando Tsuda
Classe UsuarioSistemaService
@Service
public class UsuarioSistemaService implements UserDetailsService {

@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
// LÓGICA PARA CARREGAR UM USUÁRIO VÁLIDO PELO USERNAME
// FORNECIDO

Prof. Fernando Tsuda


Classe SecurityConfig (1/3)
@Configuration
// @EnableMethodSecurity // <=== Habilita uso do @PreAuthorize e @PostAutorize
public class SecurityConfig {

// Delegating Password Encoder – suporte a múltiplos algoritmos de hash


@Bean
PasswordEncoder passwordEncoder() {
Map<String, PasswordEncoder> encoders = new HashMap<>();
BCryptPasswordEncoder bcryptEnc = new BCryptPasswordEncoder();
[Link]("bcrypt", bcryptEnc); // {bcrypt}HASH
[Link]("noop", [Link]()); // {noop}SENHA
var passwordEncoder = new DelegatingPasswordEncoder("bcrypt", encoders);
[Link](bcryptEnc);
return passwordEncoder;
}
// CONTINUA 2 ->

Prof. Fernando Tsuda


Classe SecurityConfig (2/3)
// -> CONTINUAÇÃO 2

// Bean authenticationManager - Usado para iniciar o fluxo de autenticação


@Bean
AuthenticationManager authenticationManager(
UsuarioSistemaService usuarioService,
PasswordEncoder passwordEncoder) {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
[Link](usuarioService);
[Link](passwordEncoder);
return new ProviderManager(authProvider);
}

// CONTINUA 3 ->

Prof. Fernando Tsuda


Classe SecurityConfig (3/3)
// -> CONTINUAÇÃO 3

// filterChain - Configuração geral dos parâmetros do Spring Security


// que serão ativados e pode-se configurar as autorizações de acesso
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.cors(cors -> [Link]())
.csrf(csrf -> [Link]())
.headers(headers -> [Link](fo -> [Link]())) // Permite mostrar H2 Console
.formLogin(formLogin -> [Link]())
.authorizeHttpRequests(authorize
-> authorize
.requestMatchers("/login", "/[Link]", "/[Link]",
"/h2-console/**",
"/[Link]", "/swagger-ui/**", "/v3/api-docs/**").permitAll()
.requestMatchers("/admin").hasAuthority("SCOPE_ADMIN")
.anyRequest().authenticated())
.build();
}

Prof. Fernando Tsuda


JWT - JSON Web Token
• Token com informações autocontidas a respeito do contexto onde ele será
usado
• RFC 7519
• Composto de informações denominadas "claims"
• Os dados são "codificados", porém são legíveis após a decodificação.
• O JWT prevê um mecanismo de assinatura para garantir a integridade das
informações (alterações no payload também alteram a assinatura)
• Composto de 3 partes, separadas por um "." (ponto)
• Header
• Payload → Dados do usuário que se logou + informações de validade
• Assinatura

Prof. Fernando Tsuda


Para criar/verificar JWT,
JWT - JSON Web Token acessar
[Link]
HEADER PAYLOAD (DADOS/CLAIMS)
{ {
"alg": "HS256", "sub": "fulano",
"typ": "JWT" "name": "Fulano da Silva",
} "iat": 1516239022
} Trecho do token marcado em
base64UrlEncode base64UrlEncode verde é usado para gerar
assinatura

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmdWxhbm8iLCJuYW1lIjoiRnVsYW5vI
GRhIFNpbHZhIiwiaWF0IjoxNTE2MjM5MDIyfQ.jz3N590LAtw2TLMbcq-w95w3yqhOMS2fxM52-
fiTL1w

ASSINATURA
HMACSHA256(base64UrlEncode(HEADER) + "." + base64UrlEncode(PAYLOAD), segredo256bits)

Prof. Fernando Tsuda


Implementar mecanismo de criação do JWT
• Adicionar dependência para oauth2-resource-server no [Link]
• Criar as seguintes classes:
• JwtConfig - Beans para codificação e decodificação do JWT usando recursos
da biblioteca Nimbus (padrão usado pelo Spring Security)
• JwtService - Serviços para converter UsuarioSistema para JWT e vice-versa
• JwtAuthenticationFilter - Filtro para verificar se o JWT foi enviado no
cabeçalho HTTP Authorization e converter para objeto UsuarioSistema
• Uma vez que o token foi concedido, a aplicação deve confiar nas informações que estão
nele.
• No login, gerar JWT e retornar ao usuário

Prof. Fernando Tsuda


Dependência [Link]
<!-- SPRING SECURITY STARTER PADRÃO – PODE REMOVER SE USAR DEPENDÊNCIA ABAIXO -->
<!-- <dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency> -->

<!-- PARA USAR JWT, ADICIONAR A DEPENDÊNCIA ABAIXO E REMOVER O starter-security -->
<!-- JA INCLUI O STARTER PADRÃO ACIMA -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

Prof. Fernando Tsuda


Classe JwtConfig (1/2)
@Configuration
public class JwtConfig {

// Chave simétrica para assinatura do JWT


private static final String CHAVE_ASSINATURA_JWT = "cH@v353cr37@"; // NÃO DEIXAR NO CÓDIGO

// Bean para a SecretKey - Chave simétrica usada tanto para codificar quanto decodificar com HMAC
@Bean
public SecretKey jwtSecretKey() {
try {
byte[] decodedKey = [Link]("SHA-256")
.digest(CHAVE_ASSINATURA_JWT.getBytes(StandardCharsets.UTF_8));
// Garante que a chave tem tamanho suficiente para HS256 (32 bytes)
if ([Link] < 32) { // 256 bits
// Poderia lançar uma exceção aqui para impedir a inicialização
throw new IllegalArgumentException("Deve ter pelo menos 256 bits.");
}
return new SecretKeySpec(decodedKey, 0, [Link], "HmacSHA256");
} catch (NoSuchAlgorithmException ex) {
throw new RuntimeException(ex);
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException("Chave secreta JWT Base64 inválida.", ex);
}
}
// CONTINUA 1 ->
Prof. Fernando Tsuda
Classe JwtConfig (2/2)
// -> CONTINUAÇÃO 1
// Bean para o JWKSource (necessário pelo NimbusJwtEncoder)
@Bean
public JWKSource<SecurityContext> jwkSource(SecretKey secretKey) {
// Cria um JWK do tipo OctetSequenceKey para HMAC
JWK jwk = new [Link](secretKey).build();
JWKSet jwkSet = new JWKSet(jwk);
return new ImmutableJWKSet<>(jwkSet);
}

// Bean para o JwtEncoder (usa JWKSource)


@Bean
public JwtEncoder jwtEncoder(JWKSource<SecurityContext> jwkSource) {
return new NimbusJwtEncoder(jwkSource);
}

// Bean para o JwtDecoder (usa a SecretKey diretamente para HMAC)


@Bean
public JwtDecoder jwtDecoder(SecretKey secretKey) {
// Configura o decoder para usar a chave secreta e o algoritmo HMAC SHA-256
return [Link](secretKey)
.macAlgorithm(MacAlgorithm.HS256) // Especifica o algoritmo esperado
.build();
}

} Prof. Fernando Tsuda


Classe JwtService (1/4)
@Service
public class JwtService {

@Autowired
private JwtEncoder jwtEncoder;

@Autowired
private JwtDecoder jwtDecoder;

private int intervaloExpiracao = 10; // 10 minutos

// Gera um token JWT para o usuário usando JwtEncoder


public String gerarJwt(UsuarioSistema usuario) {
Instant now = [Link]();
Instant expiry = [Link](intervaloExpiracao,
[Link]);

// Extrai as roles do UserDetails


List<String> permissoes = new ArrayList<>();
for (Permissao p : [Link]()) {
[Link]([Link]());
}

Prof. Fernando Tsuda


Classe JwtService (2/4)
// Define as claims do token
JwtClaimsSet claims = [Link]()
.issuer("pessoas-crud") // Emissor
.issuedAt(now) // Data de emissão
.expiresAt(expiry) // Data de expiração
.subject([Link]()) // Subject (username no nosso caso)
.claim("name", [Link]())
.claim("roles", permissoes) // Claim customizada com as roles
.build();

// Define o cabeçalho JWS - Usamos MacAlgorithm.HS256 que corresponde ao HmacSHA256


JwsHeader jwsHeader = [Link](MacAlgorithm.HS256).build();

// Codifica o token usando o JwtEncoder


try {
Jwt jwt = [Link]([Link](jwsHeader, claims));
return [Link]();
} catch (JwtEncodingException ex) {
// [Link]("Erro ao codificar token JWT: {}", [Link](), ex);
throw new RuntimeException("Erro ao gerar token JWT", ex);
}
}

Prof. Fernando Tsuda


Classe JwtService (3/4)
public UsuarioSistema obterUsuarioDoToken(String token) {
try {
Jwt jwt = decodificarToken(token);
final String username = [Link]();
List<String> permissoesToken = [Link]("roles");
List<Permissao> permissoes = new ArrayList<>();
for (String p : permissoesToken) {
[Link](new Permissao(p));
}
// CRIAR OBJETO COM DADOS DO USUARIO LOGADO
UsuarioSistema usuario = new UsuarioSistema([Link]("name"),
username, null, permissoes);
return usuario;
} catch (JwtException ex) {
// [Link]("Validação do JWT falhou: {}", [Link]());
}
return null;
}

Prof. Fernando Tsuda


Classe JwtService (4/4)
private Jwt decodificarToken(String token) throws JwtException {
try {
// O decoder já valida assinatura, expiração (com alguma tolerância talvez), e claims padrão
return [Link](token);
} catch (BadJwtException ex) {
// [Link]("Token JWT mal formado ou inválido: {}", [Link]());
throw ex; // Relança a exceção específica
} catch (JwtException ex) {
// [Link]("Erro inesperado ao decodificar JWT: {}", [Link](), e);
throw ex; // Relança outras exceções JWT
}
}
}

Prof. Fernando Tsuda


Classe JwtAuthenticationFilter (1/2)
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

@Autowired
private JwtService jwtService;

@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain)
throws ServletException, IOException {

final String authHeader = [Link]("Authorization");


if (authHeader == null || ![Link]("Bearer ")) {
[Link](request, response);
return;
}

final String jwt = [Link](7);

Prof. Fernando Tsuda


Classe JwtAuthenticationFilter (2/2)
try {
UsuarioSistema usuario = [Link](jwt);
if (usuario == null) {
// [Link]("Token JWT inválido ou expirado detectado para o usuário '{}'.", userEmail);
// Não lançar exceção aqui, apenas não autentica
[Link]();
}
if ([Link]().getAuthentication() == null) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
usuario,
null,
[Link]()
);
[Link](new WebAuthenticationDetailsSource().buildDetails(request));
[Link]().setAuthentication(authToken);
}
} catch (Exception ex) {
// Não lançar exceção aqui, apenas não autentica
// [Link]("Erro ao processar token JWT no filtro: {}", [Link]());
[Link]();
}
[Link](request, response);
}
}
Prof. Fernando Tsuda
Alterar filterChain no SecurityConfig
@Autowired
private JwtAuthenticationFilter jwtAuthFilter;

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

return http
.cors(cors -> [Link]())
.csrf(csrf -> [Link]())
.headers(headers -> [Link](fo -> [Link]())) // Permite mostrar H2 Console
.formLogin(formLogin -> [Link]())
// .sessionManagement(session -> [Link]([Link]))
.authorizeHttpRequests(authorize
-> authorize
.requestMatchers("/login", "/[Link]", "/[Link]",
"/h2-console/**",
"/[Link]", "/swagger-ui/**", "/v3/api-docs/**").permitAll()
// .requestMatchers("/peao").hasAuthority("SCOPE_PEAO")
// .requestMatchers("/gerente").hasAuthority("SCOPE_GERENTE")
// .requestMatchers("/diretor").hasAuthority("SCOPE_DIRETOR")
.anyRequest().authenticated())
// Injetar e adicionar filtro JWT ANTES do filtro padrão de Username/Password
.addFilterBefore(jwtAuthFilter, [Link])
.build();
} Prof. Fernando Tsuda
Spring Security – Integração com Swagger
• Para que o Swagger envie o JWT nas requisições, adicionar no projeto
a seguinte classe de configuração

@Configuration
@SecurityScheme(
name = "bearer-jwt",
type = [Link],
bearerFormat = "JWT",
scheme = "bearer"
)
public class SwaggerConfig {

Prof. Fernando Tsuda


Spring Security – Integração com Swagger
• Nas classes Controller, incluir a anotação abaixo na classe toda ou nos
métodos que necessitam de autenticação
@RestController
@SecurityRequirement(name = "bearer-jwt") // Aplica para todos endpoints
public class DadosController {

@Autowired
private UsuarioSistemaService usuarioService;

@GetMapping("/me")
// @SecurityRequirement(name = "bearer-jwt") // Somente neste método
public UsuarioSistemaDto obterDados(Authentication authn) {

// ...
}
}

Prof. Fernando Tsuda


Spring Security – Integração com frontend
• Implementar tela HTML + JS para tratar o token recebido
• Manter JWT em LocalStorage/SessionStorage como string ou em Cookie http-
only + secure
• Alterar código do Fetch API para enviar o token no cabeçalho "Authorization"
• Buscar informações do usuário → endpoint "/me“
• O username deve ser obtido do JWT decodificado

Prof. Fernando Tsuda


JWT - JSON Web Token
• Como "ler" o token usando Javascript -
[Link]
function decodificarJwt(jwt) {
const jwtParts = [Link]('.');
// Converte para base64 padrão (jwt usa base64Url)
const b64 = jwtParts[1].replace(/-/g, '+').replace(/_/g, '/’); // Extrai payload
const jwtData = decodeURIComponent(atob(b64)
.split('')
.map(c => '%' + ('00' + [Link](0).toString(16)).slice(-2))
.join(''));
alert('Dados token: ' + jwtData);
return [Link](jwtData);
}

Prof. Fernando Tsuda


Boas práticas
• OAuth2/OpenID
• Usado em aplicações famosas como Google, Azure AD, Facebook, etc
• 2FA/MFA (Two-factor authentication/Multi-factor authentication)
• Uso de passkeys – senhas temporárias enviadas por outro meio (ex:
e-mail)
• Spring Authorization Server
• Keycloak

Prof. Fernando Tsuda


Referências Spring para Webservices REST
• [Link]
reference/htmlsingle
• [Link]
boot/docs/current/reference/htmlsingle/
• [Link]
• [Link] (Vídeos Michelli
Brito)
• [Link] (Vídeos
Fernanda Kipper)

Prof. Fernando Tsuda


Referências PWA e REST
• [Link]
• [Link]
• [Link]
• [Link]
• [Link]
apps/
• [Link]
• [Link]

Prof. Fernando Tsuda

Você também pode gostar