JWT com Spring Security – Tutorial Passo a Passo com Java 17

Compartilhar:

JWT (JSON Web Token) é um padrão aberto (RFC 7519) que oferece um meio compacto e independente para transmitir informações entre as partes na forma de um objeto JSON. Hoje você vai aprender a como implementar JWT com Spring Boot de uma forma bem detalhada.

As informações são muito confiáveis e podem ser facilmente verificadas porque são assinadas digitalmente. Os JWTs podem ser assinados com um segredo (usando o algoritmo HMAC) ou um par de chaves pública/privada (usando os algoritmos RSA ou ECDSA).

jwt spring security

Projeto JWT com Spring Boot e Java 17

Em nosso projeto, vamos criar uma Api Rest com autenticação de segurança com Spring Security e JWT, em primeiro momento, você precisa somente de ter um projeto, segue abaixo os requisitos para iniciar o projeto:

  • Java 17
  • Spring Boot 3.x.x
  • PosgtreSQL ou outro banco de dados
  • Postman

Importante: para que seu projeto rode certinho, é importante utilizar a versão 17 do Java e versão 3.x.x do Spring Boot, caso contrario você pode enfrentar um erro como esse: erro Spring Boot.

Repositório do projeto no GitHub: guilhermeJWT/security-jwt.

Resultado final ao longo deste tutorial

Ao longo deste tutorial passo a passo, você vai conseguir gerar o Token JWT com uma autenticação bem completa, veja o resultado final:

jwt com spring security na prática

Dica: se você estiver utilizando a versão 17 do Java e a versão 3.x.x superior do Spring Boot, basta COPIA e COLAR que vai dar tudo certo =).

Configuração do Projeto

Adicione as seguintes dependências no arquivo pom.xml:

		<dependency>
		    <groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

		<dependency>
			<groupId>com.auth0</groupId>
			<artifactId>java-jwt</artifactId>
			<version>4.4.0</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

Logo após adicionar as dependências, você precisa configurar sua conexão com o Banco de Dados, em nosso projeto vamos utilizar o PostgreSQL na versão 12, mais você pode utilizar qualquer outro banco da sua preferência.

Abaixo as configurações de conexão:

spring.application.name=security-jwt
spring.datasource.url=jdbc:postgresql://localhost:5432/jwtsecurity
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=update

Se você estiver utilizando o Docker, você pode seguir esse passo a passo de como subir uma: imagem do Postgres.

Estrutura de Pacotes do Projeto

Nosso projeto irá seguir está estrutura de pacotes, mais você pode separar as classes da forma que você achar mais produtiva de entender, segue abaixo nossa estrutura:

No pacote MODEL, adicione as seguintes classes: ModelUser, ModelRole, ModelUserDetailsImpl.

Essas classes serão importantes para as configurações de autenticação de usuários que vamos fazer ao longo do tutorial, de primeiro momento já deixe elas prontas para uso:

Classe: ModelUser

package br.com.virandoprogramador.security_jwt.model;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.List;

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@Table(name = "modeluser")
@Entity
public class ModelUser implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String email;

    private String password;

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
    @JoinTable(name="users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name="role_id"))
    private List<ModelRole> roles;
  
}

Classe: ModelRole

package br.com.virandoprogramador.security_jwt.model;

import br.com.virandoprogramador.security_jwt.enums.Role;
import jakarta.persistence.*;
import lombok.*;


@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@Table(name="roles")
public class ModelRole {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Enumerated(EnumType.STRING)
    private Role name;

}

Classe: ModelUserDetailsImpl

package br.com.virandoprogramador.security_jwt.model;

import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.stream.Collectors;

@Getter
public class ModelUserDetailsImpl implements UserDetails {

    private ModelUser modelUser;

    public ModelUserDetailsImpl(ModelUser modelUser) {
        this.modelUser = modelUser;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return modelUser.getRoles()
                .stream()
                .map(role -> new SimpleGrantedAuthority(
                        role.getName().name()))
                .collect(Collectors.toList());
    }

    @Override
    public String getPassword() {
        return modelUser.getPassword();
    }

    @Override
    public String getUsername() {
        return modelUser.getEmail();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

}

No pacote ENUMS, adicione o seguinte Enum para definir as Roles dos Usuários:

Enum: Role

package br.com.virandoprogramador.security_jwt.enums;

public enum Role {
    ROLE_USER,
    ROLE_ADMIN,
    ROLE_GERENTE,
    ROLE_VENDEDOR
}

No pacote DTO, Precisamos criar 4 classes(Record) que serão utilizados para usar na Api, este tipo de classe foi introduzido no Java 14, mais você pode utilizar uma classe normalmente.

Segue abaixo as classes: CreateUserDTO, JwtTokenDTO, LoginUserDTO, UserDTO.

Record: CreateUserDTO

package br.com.virandoprogramador.security_jwt.dto;

import br.com.virandoprogramador.security_jwt.enums.Role;

public record CreateUserDTO(String email, String password, Role role) {
  
}

Record: JwtTokenDTO

package br.com.virandoprogramador.security_jwt.dto;

public record JwtTokenDTO(String token) {
  
}

Record: LoginUserDTO

package br.com.virandoprogramador.security_jwt.dto;

public record LoginUserDTO(String email, String password) {
  
}

Record: UserDTO

package br.com.virandoprogramador.security_jwt.dto;

import br.com.virandoprogramador.security_jwt.enums.Role;

import java.util.List;

public record UserDTO(Long id, String email, List<Role> roles) {
  
}

No pacote REPOSITORY, adicione a seguinte interface para que seja possível utilizar os métodos do Spring Data Jpa, a interface será utilizada para algumas funções ao longo do tutorial.

Interface: UserRepository

package br.com.virandoprogramador.security_jwt.repository;

import br.com.virandoprogramador.security_jwt.model.ModelUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface UserRepository extends JpaRepository<ModelUser, Long> {

    Optional<ModelUser> findByEmail(String email);

}

Na camada de repository, temos o método findByEmail, que recebe o e-mail de um usuário, ele é utilizado para pesquisar no Banco de Dados se existe algum Usuário com este e-mail, com isso podemos buscar suas credenciais, e autenticar na aplicação.

Camada de Segurança com Spring Security e Token JWT

Agora vamos começar o processo de adicionar segurança em nossa Api, nos pacotes SECURITY e SERVICE, são separadas as classes de configuração, nesta etapa você deve ter bastante atenção para que as configurações sejam aplicadas corretamente.

Importante: se você estiver copiando e colando os códigos, certamente você vai se deparar com algum erro por falta de classes, continue o tutorial para que os erros desapareçam.

Estrutura das Classes

No pacote SECURITY, vamos criar 2 classes, SecurityConfig e UserAuthenticationFilter, elas serão responsáveis para configurar a camada de segurança e autenticação do usuário.

Classe: SecurityConfig

package br.com.virandoprogramador.security_jwt.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    private UserAuthenticationFilter userAuthenticationFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().authorizeHttpRequests()
                .requestMatchers("api/users/**").permitAll()
                .anyRequest().denyAll()
                .and().
                    addFilterBefore(userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

A classe SecurityConfig é responsável por configurar como deve funcionar a segurança, é a principal configuração para definir quais rotas serão acessadas ou autenticadas, a anotação @EnableWebSecurity habilita a configuração de segurança para a aplicação.

Automaticamente, o Spring Boot entende que essa classe será adicionada métodos como authenticationManager e securityFilterChain.

Observação: note que na linha 28, estamos permitindo o acesso para a seguinte rota: “api/users”, essa rota será utilizada para realizar a autenticação de usuário e criação de um novo usuário na Api, vamos utilizar elas daqui a pouco para testar a aplicação.

Outro ponto importante, essa rota deve ser liberada para todos que tiverem acesso na Api, por isso definimos a configuração .permitAll(), pense comigo, como vamos acessar uma tela de login se não temos autorização pra isso? por esse motivo, devem ser liberadas.

Classe: UserAuthenticationFilter

package br.com.virandoprogramador.security_jwt.security;

import br.com.virandoprogramador.security_jwt.model.ModelUser;
import br.com.virandoprogramador.security_jwt.model.ModelUserDetailsImpl;
import br.com.virandoprogramador.security_jwt.repository.UserRepository;
import br.com.virandoprogramador.security_jwt.service.JwtTokenService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Arrays;

@Component
public class UserAuthenticationFilter extends OncePerRequestFilter{

    @Autowired
    private JwtTokenService jwtTokenService;

    @Autowired
    private UserRepository userRepository;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (verificaEndpointsPublicos(request)) {
            String token = recuperaToken(request);
            if (token != null) {
                String subject = jwtTokenService.pegarToken(token);
                ModelUser modelUser = userRepository.findByEmail(subject).get();
                ModelUserDetailsImpl modelUserDetails = new ModelUserDetailsImpl(modelUser);
                Authentication authentication =
                        new UsernamePasswordAuthenticationToken(
                                modelUserDetails.getUsername(),
                                null,
                                modelUserDetails.getAuthorities());

                SecurityContextHolder.getContext().setAuthentication(authentication);
            } else {
                throw new RuntimeException("Token inexistente!");
            }
        }
        filterChain.doFilter(request, response);
    }

    private boolean verificaEndpointsPublicos(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        return !Arrays.asList("/api/users/login", "/api/users").contains(requestURI);
    }

    private String recuperaToken(HttpServletRequest request) {
        String authorizationHeader = request.getHeader("Authorization");
        if (authorizationHeader != null) {
            return authorizationHeader.replace("Bearer ", "");
        }
        return null;
    }

}

Importante: ao adicionar essa classe ao projeto, você irá se deparar com o erro da falta da classe JwtTokenService, essa classe vamos criar no próximo passo.

No pacote SERVICE, vamos precisar criar 3 classes: JwtTokenService, UserDetailServiceImpl e UserService.

Essa camada da aplicação, ficará responsável pela regra de negócio das autenticações, como geração do Token JWT, autenticar o Usuário entre outras.

Classe: JwtTokenService

package br.com.virandoprogramador.security_jwt.service;

import br.com.virandoprogramador.security_jwt.model.ModelUserDetailsImpl;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

@Service
public class JwtTokenService {

    @Value("${token.jwt.secret.key}")
    private String secret_Key;

    @Value("${token.jwt.issuer}")
    private String issuer;

    public String generateToken(ModelUserDetailsImpl user) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret_Key);
            return JWT.create()
                    .withIssuer(issuer)
                    .withIssuedAt(dataCriacao())
                    .withExpiresAt(dataExpiracao())
                    .withSubject(user.getUsername())
                    .sign(algorithm);
        } catch (JWTCreationException exception){
            throw new JWTCreationException("Erro ao gerar o token: ", exception);
        }
    }

    public String pegarToken(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret_Key);
            return JWT.require(algorithm)
                    .withIssuer(issuer)
                    .build()
                    .verify(token)
                    .getSubject();
        } catch (JWTVerificationException exception){
            throw new JWTVerificationException("Token inválido ou expirado!");
        }
    }

    private Instant dataExpiracao() {
        return ZonedDateTime.now(ZoneId.of("America/Sao_Paulo"))
                .plusHours(2).toInstant();
    }

    private Instant dataCriacao() {
        return ZonedDateTime.now(ZoneId.of("America/Sao_Paulo")).toInstant();
    }

}

Nesta classe, estamos realizando a geração do token pegando os valores de secret_Key, issuer, dataCriacao, dataExpiracao e username do Usuário.

No método abaixo, estamos realizando a leitura deste token para validação.

Observação: note que na linha 18 e 21 estamos definindo 2 valores para as variáveis secret_Key e issuer, vamos precisar dessas configurações para definir uma chave secreta, segue abaixo os valores das variáveis no arquivo application.properties.

token.jwt.secret.key=virandoprogramador-secret-key
token.jwt.issuer=virandoprogramador-exemple-issuer

Classe: UserDetailsService

package br.com.virandoprogramador.security_jwt.service;

import br.com.virandoprogramador.security_jwt.model.ModelUser;
import br.com.virandoprogramador.security_jwt.model.ModelUserDetailsImpl;
import br.com.virandoprogramador.security_jwt.repository.UserRepository;
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;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        ModelUser modelUser = userRepository.findByEmail(username)
                .orElseThrow(() -> new RuntimeException("Usuário não encontrado!"));
        return new ModelUserDetailsImpl(modelUser);
    }
}

Nesta classe, temos um único método que é carregar um Usuário pelo username(e-mail), vamos precisar deste método para realizar a verificação do Usuário posteriormente.

Classe: UserService

package br.com.virandoprogramador.security_jwt.service;

import br.com.virandoprogramador.security_jwt.dto.CreateUserDTO;
import br.com.virandoprogramador.security_jwt.dto.JwtTokenDTO;
import br.com.virandoprogramador.security_jwt.dto.LoginUserDTO;
import br.com.virandoprogramador.security_jwt.model.ModelRole;
import br.com.virandoprogramador.security_jwt.model.ModelUser;
import br.com.virandoprogramador.security_jwt.model.ModelUserDetailsImpl;
import br.com.virandoprogramador.security_jwt.repository.UserRepository;
import br.com.virandoprogramador.security_jwt.security.SecurityConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private SecurityConfig securityConfig;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenService jwtTokenService;

    public void salvarUsuario(CreateUserDTO createUserDto) {
        ModelUser newUser = ModelUser.builder()
                .email(createUserDto.email())
                .password(securityConfig.passwordEncoder().encode(createUserDto.password()))
                .roles(List.of(ModelRole.builder().name(createUserDto.role()).build()))
                .build();

        userRepository.save(newUser);
    }

    public JwtTokenDTO autenticarUsuario(LoginUserDTO loginUserDto) {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(loginUserDto.email(), loginUserDto.password());

        Authentication authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        ModelUserDetailsImpl modelUserDetails = (ModelUserDetailsImpl) authentication.getPrincipal();
        return new JwtTokenDTO(jwtTokenService.generateToken(modelUserDetails));
    }
}

Nesta classe, temos 2 métodos para salvar um novo Usuário e autenticar um Usuário existente, também será muito importante nos próximos passos.

Testando a Api com Spring Security e JWT

Estamos chegando no final, mais antes precisamos criar uma camada de Controller, onde ficará nossos endpoits para testar a criação e validação de segurança.

No pacote CONTROLLER, crie a seguinte classe: UserController, ela terá basicamente 2 métodos, loginUsuario e salvarUsuario.

Classe: UserController

package br.com.virandoprogramador.security_jwt.controller;

import br.com.virandoprogramador.security_jwt.dto.CreateUserDTO;
import br.com.virandoprogramador.security_jwt.dto.JwtTokenDTO;
import br.com.virandoprogramador.security_jwt.dto.LoginUserDTO;
import br.com.virandoprogramador.security_jwt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/login")
    public ResponseEntity<JwtTokenDTO> loginUsuario(@RequestBody LoginUserDTO loginUserDto) {
        JwtTokenDTO token = userService.autenticarUsuario(loginUserDto);
        return new ResponseEntity<>(token, HttpStatus.OK);
    }

    @PostMapping
    public ResponseEntity<Void> salvarUsuario(@RequestBody CreateUserDTO createUserDto) {
        userService.salvarUsuario(createUserDto);
        return new ResponseEntity<>(HttpStatus.CREATED);
    }
}

Para testar nossa aplicação, precisamos entender as rotas, observe que nossa api começa com /api/users, agora é só testar, no meu caso estou utilizado o projeto local, então minha rota( e possivelmente a sua ) deve ser:

localhost:8080/api/users/login e localhost:8080/api/users.

Agora precisamos testar, para isso você vai precisar de algum Software de teste de Api, como Postman e Insomnia.

Criando um novo Usuário

Para criar um novo Usuário, acesse a seguinte rota: localhost:8080/api/users com o método POST, no campo body do Postman, vá em raw e em seguida selecione JSON:

token jwt com spring security

Opa! criamos um novo Usuário no banco de dados, observe o status 201 Created, que significa que a requisição deu certo e que foi criado um registro no servidor.

A classe que recebe os dados de um novo Usuário é a CreateUserDTO, recebendo o email, password e a role.

Bora ver o user salvo no Postgres? acesse seu banco de dados e vá na tabela modeluser.

spring security jwt

Observação: note que o password está criptografado no banco de dados, para que isso seja possível, utilizamos a classe BCryptPasswordEncoder para criptografar a senha e salvar no banco de dados. Desta forma, conseguimos garantir que se nosso banco de dados for hackeado, o atacante não conseguira identificar a senha real, precisaria de um algoritimo hash, que somente nossa aplicação consegue entender.

Autenticando o Usuário na Api com o Token JWT

Como você viu no começo do artigo, vamos autenticar na aplicação, utilizando as credenciais que acabamos de criar.

Para autenticar na api acesse: localhost:8080/api/users/login, método POST com email e password que você cadastrou.

jwt spring boot

Prontinho, veja que no corpo da requisição retornou código 200 OK, que significa que a requisição deu tudo certo, a validação de Usuário, retornando o Token.

Para testar as outras rotas da sua aplicação, você precisa pegar o Token e adicionar no campo Authorization -> Bearer Token -> Inserir o Token.

Considerações finais

Em resumo, neste artigo, fornecemos um guia passo a passo detalhado sobre como implementar JSON Web Token (JWT) com Spring Boot. Desde a configuração inicial até a integração com a autenticação de usuário, nosso objetivo foi oferecer uma compreensão abrangente de como esse processo funciona.

Ao longo do artigo, você conheceu os fundamentos do JWT e como ele pode ser utilizado para garantir a segurança das nossas aplicações. Demonstramos como configurar o Spring Security para lidar com a autenticação de usuários de forma eficiente, proporcionando uma base sólida para a construção de sistemas robustos.

Além disso, criamos uma aplicação de exemplo completa, demonstrando na prática como todas essas peças se encaixam. Com isso, os leitores podem não apenas compreender os conceitos teóricos, mas também aplicá-los em projetos reais.

Portanto, encorajamos você a utilizar este projeto como ponto de partida em suas próprias aplicações. A implementação de JWT com Spring Boot não apenas fortalecerá a segurança do seu sistema, mas também proporcionará uma experiência de usuário mais segura.

Esperamos que este artigo tenha sido útil e que você possa aproveitar ao máximo os conhecimentos adquiridos aqui. Compartilhe nos grupos para ajudar mais Desenvolvedores Java. Obrigado por ler!

Perguntas Frequentes sobre Token JWT

Abaixo, irei responder algumas dúvidas bem comuns em relação ao Token JWT:

O que um token JWT faz?

Basicamente, um token JWT funciona como um mecanismo de autenticação e autorização, permitindo que um usuário prove sua identidade e acesse recursos de forma segura em um sistema distribuído. Ao transmitir informações em formato JSON, o token JWT codifica dados relevantes, como informações de usuário e metadados adicionais, de maneira compacta e segura.

Esses tokens são frequentemente utilizados em cenários onde a comunicação entre diferentes partes precisa ser segura e confiável, como em aplicações web, APIs e microsserviços.

Ao utilizar algoritmos de criptografia robustos, um token JWT pode garantir a integridade e a confidencialidade das informações transmitidas, tornando-o uma escolha popular para implementações de segurança em ambientes distribuídos.

Qual é a diferença entre JWT e Token normal?

A diferença entre JWT (JSON Web Token) e um token normal reside principalmente em onde e como são armazenados e utilizados. Um token normal, em geral, é armazenado no lado do servidor e é utilizado para autenticar solicitações subsequentes do mesmo usuário.

Por outro lado, a autenticação do lado do cliente usando JWT envolve a emissão de um token assinado para o cliente após o login bem-sucedido, que é então armazenado no lado do cliente e enviado de volta ao servidor com cada solicitação subsequente.

Em um sistema com token normal, quando um usuário faz login, o servidor autentica suas credenciais e, em seguida, gera um token que é associado à sessão do usuário no servidor. Esse token é então armazenado no lado do servidor e enviado de volta ao cliente, geralmente como um cookie HTTP. Com cada solicitação subsequente, o token é enviado de volta ao servidor para autenticar o usuário.

Por outro lado, com JWT, após o login bem-sucedido, o servidor emite um token JWT assinado para o cliente, contendo informações de autenticação e autorização. Esse token é então armazenado no lado do cliente, geralmente em local storage ou em um cookie seguro.

Com cada solicitação subsequente, o cliente envia o token JWT de volta ao servidor no cabeçalho da requisição. O servidor pode então validar a autenticidade e a integridade do token JWT sem a necessidade de consultar o armazenamento de sessão no servidor.

Os Tokens JWT são seguros?

Um dos pontos-chave a se considerar é que os tokens JWT contêm uma assinatura criptográfica, o que pode dar a impressão de que são bastante seguros. No entanto, a presença de uma assinatura não é uma garantia absoluta de segurança. Assim como qualquer outra tecnologia de segurança, os tokens JWT são tão seguros quanto a implementação em que são utilizados.

Além disso, a segurança dos tokens JWT também depende da maneira como são gerenciados e protegidos durante todo o seu ciclo de vida. Por exemplo, se um token for armazenado de forma inadequada no lado do cliente, como em um local storage vulnerável a ataques de cross-site scripting (XSS), isso pode comprometer a segurança do sistema.

Outro aspecto é a validação adequada dos tokens JWT pelo servidor. Sem uma validação adequada, os tokens JWT podem ser suscetíveis a ataques de falsificação, manipulação ou replay.

4.7/5 - (3 votos)
Compartilhar:

4 comentários

  1. Estou estudando esse assunto, mas pela plataforma que estou estudando acabei com um projeto sem concluir, pois não entendi bem a explicação nem o que foi feito. Agora com o conteúdo que você criou isso ficou bem mais claro. Obrigado pelo seu tempo e disposição em criar esse conteúdo!

  2. Amigo, antes de tudo sou muito grato por essa explicação e esse tutorial, porém encontrei o seguinte erro abaixo:
    – Na classe UserAuthenticationFilter temos uma variavel do tipo string recebendo o valor de jwtTokenService.getSubjectFromToken(token)
    porém essa função do JwtTokenService não existe.

    • Olá Willians, obrigado pelo seu comentário, realmente, no momento que estive criando o post alterei o nome do método, vou alterar no artigo, na classe JwtTokenService na linha 38 tem o método chamado “pegarToken”, é o método que seria utilizado na classe UserAuthenticationFilter, por engano acabei alterando o nome, mais o método é esse, acabei de atualizar, me confirma se funcionou tudo certinho. Obrigado =)

Deixe um comentário

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