Springboot

JWT3x

Json Web Token com Spring Boot 3x

Neste tutorial iremos ilustrar as mudanças em configurar e habilitar segurança utilizando Spring Boot 3x com JWT.

🔔 Atenção
Grande parte das configurações e ilustrações já foram abordadas no tutoria JWT2x onde agora iremos pontuar as modificações necessárias para a migração do Spring Boot 2x para o Spring Boot 3x.

pom.xml

Revisa abaixo as versões das dependências já existentes no projeto ou adiciona conforme código abaixo:

<!-- Spring Boot 3x -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.4</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>
<!-- JWT compatível -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.1</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.1</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.1</version>
    <scope>runtime</scope>
</dependency>
<!-- API do Swagger -->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.7.0</version>
</dependency>
<!-- Interface Gráfica -->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.3.0</version>
</dependency>

chave token

Para garantir a segurança do JWT gerado é recomendado gerar uma chave privada conforme novas orientações abaixo:

import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.util.Base64;
public class JwtSecretKey {
    public static void main(String[] args) {
        System.out.println(new String(Base64.getEncoder().encode(Keys.secretKeyFor(SignatureAlgorithm.HS512).getEncoded())));

        //saida ilustrativa
        //25L+x4ic5gLDyYtOsVsLf40sX54Y8SoJ4/oCXqG9p2uzlKsPRiuu8+NRnzsoOEuALfZBT7Xe3pu/d/YQ5ZEdCw==
    }
}

O resultado deverá ser inserido no application.propeties

security.config.key=25L+x4ic5gLDyYtOsVsLf40sX54Y8SoJ4/oCXqG9p2uzlKsPRiuu8+NRnzsoOEuALfZBT7Xe3pu/d/YQ5ZEdCw==

web security config

Com a mudança da versão do Spring Boot 2x para 3x o algoritimo de configuração das rotas livres ou permissionadas teve alterações pontuais de classes e sintaxe conforme abaixo.


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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 WebSecurityConfig {
    private static final String[] SWAGGER_WHITELIST = {
            "/v2/api-docs/**",
            "/v3/api-docs/**",
            "/swagger-resources",
            "/swagger-resources/**",
            "/configuration/ui",
            "/configuration/security",
            "/swagger-ui/**",
            "/webjars/**"
    };
    @Bean
    public SecurityFilterChain securityFilterChan(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity.csrf(csrf -> csrf.disable())
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests( authorize -> authorize
                        .requestMatchers(HttpMethod.POST,"/users").permitAll()
                        .requestMatchers( SWAGGER_WHITELIST).permitAll()
                        .requestMatchers(HttpMethod.POST,"/login").permitAll()
                        .requestMatchers(HttpMethod.GET,"/users").hasAnyRole("USERS","MANAGERS")
                        .requestMatchers("/managers").hasAnyRole("MANAGERS")
                        .anyRequest().authenticated()
                ).addFilterAfter(new JWTFilter(), UsernamePasswordAuthenticationFilter.class)
                .build();
    }
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception{
        return authenticationConfiguration.getAuthenticationManager();
    }
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

}