Introdução

No desenvolvimento de aplicações web modernas, a criação de APIs RESTful é fundamental para a comunicação entre diferentes sistemas. Este tutorial detalha como usar Java com o Spring Boot para construir uma aplicação RESTful que não apenas é escalável, mas também segura, utilizando a autenticação JSON Web Token (JWT). O Spring Boot simplifica o processo de configuração e desenvolvimento, permitindo que os desenvolvedores se concentrem na lógica de aplicação. Neste guia, vamos explorar cada etapa, desde a configuração do projeto até a implementação de funcionalidades complexas, garantindo que você aprenda como criar um serviço RESTful robusto e seguro.

Etapas

  1. Configuração do Ambiente de Desenvolvimento

    Primeiramente, você precisa assegurar que o JDK e o Maven estejam instalados. Verifique isso executando `java -version` e `mvn -version` no terminal. Se não estiverem instalados, siga as instruções da documentação oficial para fazer a instalação.

    commands
    # Verificando as versões instaladas
    java -version
    mvn -version

  2. Criação do Projeto Spring Boot

    Utilize o Spring Initializr (https://start.spring.io/) para gerar um novo projeto Spring Boot. Escolha as configurações: **Project**: Maven, **Language**: Java, **Spring Boot**: última versão estável, **Packaging**: Jar, **Java**: 11 ou superior. Adicione as dependências ‘Spring Web’, ‘Spring Data JPA’, ‘Spring Security’, e ‘jjwt’. Baixe e descompacte o projeto em sua máquina.

    pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.example</groupId>
      <artifactId>api-jwt</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <name>api-jwt</name>
      <description>API RESTful com Spring Boot e JWT</description>
      <properties>
        <java.version>11</java.version>
      </properties>
      <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
          <groupId>io.jsonwebtoken</groupId>
          <artifactId>jjwt</artifactId>
          <version>0.9.1</version>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
        </dependency>
      </dependencies>
      <build>
        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
        </plugins>
      </build>
    </project>

  3. Configuração do Banco de Dados H2

    Edite o arquivo `application.properties` para definir as propriedades do banco de dados H2 e habilitar o console web para visualização dos dados.

    application.properties
    spring.h2.console.enabled=true
    spring.datasource.url=jdbc:h2:mem:testdb
    spring.datasource.driverClassName=org.h2.Driver
    spring.datasource.username=sa
    spring.datasource.password=
    spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
    spring.jpa.hibernate.ddl-auto=update

  4. Configuração do Client JWT

    Implemente uma classe utilitária `JwtUtil` que será responsável pela criação e validação do token JWT.

    JwtUtil.java
    package com.example.apijwt.util;
    
    import io.jsonwebtoken.Claims;
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    import org.springframework.stereotype.Component;
    
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    @Component
    public class JwtUtil {
    
        private String secret = "minha-chave-secreta"; // Mantenha isso seguro!
        private long expirationTime = 1000 * 60 * 60; // 1 hora
    
        public String gerarToken(String username) {
            Map<String, Object> claims = new HashMap<>();
            return criarToken(claims, username);
        }
    
        private String criarToken(Map<String, Object> claims, String subject) {
            return Jwts.builder()
                    .setClaims(claims)
                    .setSubject(subject)
                    .setIssuedAt(new Date(System.currentTimeMillis()))
                    .setExpiration(new Date(System.currentTimeMillis() + expirationTime))
                    .signWith(SignatureAlgorithm.HS256, secret).compact();
        }
    
        public boolean validarToken(String token, String username) {
            final String usernameDoToken = obterUsernameDoToken(token);
            return (usernameDoToken.equals(username) && !isTokenExpirado(token));
        }
    
        private String obterUsernameDoToken(String token) {
            return obterClaims(token).getSubject();
        }
    
        private Claims obterClaims(String token) {
            return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
        }
    
        private boolean isTokenExpirado(String token) {
            return obterClaims(token).getExpiration().before(new Date());
        }
    }

  5. Implementação do Controlador de Autenticação

    Crie um controlador `AuthController` que gerencia o login e a geração do token JWT.

    AuthController.java
    package com.example.apijwt.controller;
    
    import com.example.apijwt.util.JwtUtil;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    @RequestMapping("/api/auth")
    public class AuthController {
    
        @Autowired
        private JwtUtil jwtUtil;
    
        @PostMapping("/login")
        public String login(@RequestBody Map<String, String> usuario) {
            // Aqui você pode adicionar validação do usuário
            return jwtUtil.gerarToken(usuario.get("username"));
        }
    }

  6. Criação da Entidade e Repositório de Usuário

    Implemente a classe `Usuario`, e o repositório `UsuarioRepository` para gerenciamento dos dados do usuário.

    Usuario.java
    package com.example.apijwt.model;
    
    import javax.persistence.*;
    
    @Entity
    @Table(name = "usuarios")
    public class Usuario {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(nullable = false, unique = true)
        private String username;
    
        @Column(nullable = false)
        private String password;
    
        // Getters e Setters
    }

    UsuarioRepository.java
    package com.example.apijwt.repository;
    
    import com.example.apijwt.model.Usuario;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface UsuarioRepository extends JpaRepository<Usuario, Long> {
        Usuario findByUsername(String username);
    }

  7. Configuração do Spring Security

    Implemente a configuração de segurança para proteger as rotas da API e permitir acesso somente aos usuários autenticados.

    SecurityConfig.java
    package com.example.apijwt.config;
    
    import com.example.apijwt.filter.JwtRequestFilter;
    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.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;
    import org.springframework.security.config.http.SessionCreationPolicy;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private JwtRequestFilter jwtRequestFilter;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .authorizeRequests()
                    .antMatchers("/api/auth/login").permitAll()
                    .anyRequest().authenticated()
                    .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        }
    
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            // Configurações de autenticação aqui se necessário
        }
    
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    }

  8. Implementação do Filtro de Requisição JWT

    Crie um filtro `JwtRequestFilter` que intercepta as requisições para validar o token JWT.

    JwtRequestFilter.java
    package com.example.apijwt.filter;
    
    import com.example.apijwt.util.JwtUtil;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
    import org.springframework.web.filter.OncePerRequestFilter;
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class JwtRequestFilter extends OncePerRequestFilter {
    
        @Autowired
        private JwtUtil jwtUtil;
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
            final String authorizationHeader = request.getHeader("Authorization");
            String username = null;
            String jwt = null;
    
            if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
                jwt = authorizationHeader.substring(7);
                username = jwtUtil.obterUsernameDoToken(jwt);
            }
    
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                // Autentique o usuário aqui - Implementa sua lógica
            }
            chain.doFilter(request, response);
        }
    }

  9. Executando a Aplicação e Testes

    Use o Maven para compilar e executar a aplicação. Teste os endpoints utilizando ferramentas como Postman ou cURL.

    commands
    # Compilar e executar a aplicação
    mvn spring-boot:run
    # Testes com cURL
    curl -X POST -H "Content-Type: application/json" -d '{"username":"user", "password":"password"}' http://localhost:8080/api/auth/login
    curl -X GET -H "Authorization: Bearer <token>" http://localhost:8080/api/produtos

Conclusão

Neste tutorial, você explorou como desenvolver uma aplicação RESTful escalável e segura usando Java e Spring Boot com autenticação JWT. Foi abordado desde a configuração inicial do projeto até a implementação de controle de acesso e segurança. Você agora possui a base necessária para expandir essa aplicação, implementando funcionalidades adicionais, integração com bancos de dados persistentes e refinando a segurança do seu sistema. Essa abordagem não só melhora a segurança das suas aplicações, mas também prepara você para os desafios do mercado atual.

Hashtags

#Java #SpringBoot #RESTful #JWT #Segurança #DesenvolvimentoDeSoftware