Introdução
A segurança de aplicações web é um aspecto crítico no desenvolvimento de software moderno. Neste tutorial, vamos explorar como implementar sistemas de autenticação robustos com o uso do framework Red, juntamente com bibliotecas populares como JWT (JSON Web Tokens) e OAuth. Faremos uma abordagem passo a passo, começando pela configuração do ambiente até a implementação de autenticação, autorização e testes unitários. Este guia é projetado para desenvolvedores que desejam assegurar suas aplicações web, garantindo que apenas usuários autenticados tenham acesso a recursos protegidos, enquanto também previnem fraudes e acessos indevidos.
Etapas
Configuração do Ambiente de Desenvolvimento
Antes de começarmos, você deverá ter o JDK (Java Development Kit) e o Maven instalados em sua máquina. Você pode verificar as versões instaladas rodando os seguintes comandos no terminal.
commands# Verificar versões instaladas
java -version
mvn -versionCriação do Projeto Spring Boot
Utilize o Spring Initializr para gerar um novo projeto Spring Boot com as dependências necessárias. Certifique-se de incluir as dependências ‘Spring Web’, ‘Spring Security’, ‘Spring Data JPA’, e ‘jjwt’ para trabalhar com JWT.
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>auth-system</artifactId> <version>0.0.1-SNAPSHOT</version> <name>auth-system</name> <description>API de autenticação com JWT e OAuth</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-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</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>
Configuração do Application Properties
Edite o arquivo `application.properties` para definir as propriedades do aplicativo, como a configuração do banco de dados e as propriedades de segurança básicas.
application.propertiesspring.datasource.url=jdbc:mysql://localhost:3306/auth_db spring.datasource.username=root spring.datasource.password=senha spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true
Criação da Entidade `Usuario`
Implemente a classe modelo `Usuario`, que representará os usuários na aplicação e inclui atributos como email e senha, além de anotações JPA para o mapeamento ao banco de dados.
Usuario.javapackage com.example.authsystem.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 email; @Column(nullable = false) private String senha; // Getters e Setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getSenha() { return senha; } public void setSenha(String senha) { this.senha = senha; } }
Criação do Repositório `UsuarioRepository`
Implemente a interface `UsuarioRepository`, que estende `JpaRepository` e fornece métodos para operações CRUD (Criar, Ler, Atualizar, Deletar) no banco de dados.
UsuarioRepository.javapackage com.example.authsystem.repository; import com.example.authsystem.model.Usuario; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface UsuarioRepository extends JpaRepository<Usuario, Long> { Usuario findByEmail(String email); }
Implementação do Serviço `UsuarioService`
Crie a classe `UsuarioService` que contém a lógica de negócios para a autenticação, incluindo a geração de JWT e a validação de credenciais.
UsuarioService.javapackage com.example.authsystem.service; import com.example.authsystem.model.Usuario; import com.example.authsystem.repository.UsuarioRepository; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import java.util.Date; import java.util.HashMap; import java.util.Map; @Service public class UsuarioService { @Autowired private UsuarioRepository usuarioRepository; public Usuario save(Usuario usuario) { usuario.setSenha(new BCryptPasswordEncoder().encode(usuario.getSenha())); return usuarioRepository.save(usuario); } public String gerarToken(String email) { Map<String, Object> claims = new HashMap<>(); return Jwts.builder() .setClaims(claims) .setSubject(email) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10 horas .signWith(SignatureAlgorithm.HS256, "secreta") .compact(); } public boolean validarToken(String token, String email) { final String usuario = extrairEmail(token); return (usuario.equals(email) && !isTokenExpirado(token)); } private boolean isTokenExpirado(String token) { return extrairExpiracao(token).before(new Date()); } private Date extrairExpiracao(String token) { return Jwts.parser().setSigningKey("secreta").parseClaimsJws(token).getBody().getExpiration(); } private String extrairEmail(String token) { return Jwts.parser().setSigningKey("secreta").parseClaimsJws(token).getBody().getSubject(); } }
Implementação do Controlador `AuthController`
Crie a classe `AuthController` para gerenciar endpoints relacionados à autenticação, como login e registro de usuários.
AuthController.javapackage com.example.authsystem.controller; import com.example.authsystem.model.Usuario; import com.example.authsystem.service.UsuarioService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/auth") public class AuthController { @Autowired private UsuarioService usuarioService; @PostMapping("/register") public ResponseEntity<Usuario> registrar(@RequestBody Usuario usuario) { return ResponseEntity.ok(usuarioService.save(usuario)); } @PostMapping("/login") public ResponseEntity<String> login(@RequestBody Usuario usuario) { // Aqui você deve adicionar sua lógica de validação de usuário String token = usuarioService.gerarToken(usuario.getEmail()); return ResponseEntity.ok(token); } }
Implementação de Testes Unitários
Elabore testes unitários para a classe `UsuarioService`, assegurando que as funções de criação de usuário e geração de JWT funcionem corretamente.
UsuarioServiceTest.javapackage com.example.authsystem.service; import com.example.authsystem.model.Usuario; import com.example.authsystem.repository.UsuarioRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.when; public class UsuarioServiceTest { @InjectMocks private UsuarioService usuarioService; @Mock private UsuarioRepository usuarioRepository; @BeforeEach public void init() { MockitoAnnotations.openMocks(this); } @Test public void testRegistrarUsuario() { Usuario usuario = new Usuario(); usuario.setEmail("user@example.com"); usuario.setSenha("senha123"); when(usuarioRepository.save(usuario)).thenReturn(usuario); Usuario usuarioSalvo = usuarioService.save(usuario); assertNotNull(usuarioSalvo); assertEquals(usuario.getEmail(), usuarioSalvo.getEmail()); } }
Executando a Aplicação e Testes
Utilize o Maven para compilar e executar a aplicação. Após iniciar a aplicação, use ferramentas como Postman ou cURL para testar os endpoints de registro e login.
commands# Compilar e executar a aplicação
mvn spring-boot:run
# Executar os testes
mvn testcurl_examples# Registar um novo usuário
curl -X POST -H "Content-Type: application/json" -d '{"email":"user@example.com", "senha":"senha123"}' http://localhost:8080/api/auth/register
# Fazer login
curl -X POST -H "Content-Type: application/json" -d '{"email":"user@example.com", "senha":"senha123"}' http://localhost:8080/api/auth/login
Conclusão
Neste tutorial, você aprendeu a implementar um sistema de autenticação em uma aplicação web utilizando o Spring Boot, JWT e OAuth. Discutimos desde a configuração do projeto até as implementações necessárias para suportar registro de usuários e autenticação com tokens. Com esses conhecimentos, você pode melhorar a segurança de suas aplicações, garantindo acesso restrito e autenticado, o que é essencial no ambiente atual de ameaças cibernéticas. Continue a explorar e expandir suas implementações para criar soluções ainda mais robustas.