Sistema completo de autenticação e autorização de usuários construído com Java 21, Spring Boot 4.0.5 e Spring Security 7. Implementa boas práticas de segurança prontas para produção.
| Tecnologia | Versão | Função |
|---|---|---|
| Java | 21 | Linguagem principal |
| Spring Boot | 4.0.5 | Framework base |
| Spring Security | 7.x | Autenticação e autorização |
| Spring Data JPA | 4.x | Persistência com Hibernate 7 |
| H2 Database | — | Banco em memória (desenvolvimento) |
| Thymeleaf | 4.x | Engine de templates |
| Lombok | — | Redução de boilerplate |
| Maven | 3.9+ | Build e gerenciamento de dependências |
- ✅ Cadastro de usuário comum com validação de formulário
- ✅ Login com e-mail e senha
- ✅ Redirecionamento automático por role após login
- ✅ Página home exclusiva para usuários (
ROLE_USER) - ✅ Painel exclusivo para administradores (
ROLE_ADMIN) - ✅ Logout com invalidação de sessão e limpeza de cookie
- ✅ Admin padrão criado automaticamente na primeira execução
| Proteção | Mecanismo |
|---|---|
| Senhas | BCrypt com strength 12 (~400ms/hash) |
| CSRF | HttpSessionCsrfTokenRepository em todos os POSTs |
| SQL Injection | JPA com PreparedStatements parametrizados |
| XSS | Thymeleaf escaping + Content-Security-Policy header |
| Session Fixation | changeSessionId() ao autenticar |
| Sessões simultâneas | maximumSessions(1) por usuário |
| Cookie seguro | HttpOnly=true, SameSite=Strict |
| User enumeration | Mensagens de erro genéricas no login |
| Clickjacking | X-Frame-Options: SAMEORIGIN |
| MIME sniffing | X-Content-Type-Options: nosniff |
Verifique a instalação:
java -version
# java version "21.x.x"git clone https://github.com/akaPierre/auth-system.git
cd auth-system.\mvnw.cmd spring-boot:runhttp://localhost:8080
A aplicação cria automaticamente o banco H2 em
./data/authdb.mv.dbe o admin padrão na primeira execução.
⚠️ Altere imediatamente antes de ir para produção.
| Perfil | Senha | |
|---|---|---|
| Administrador | admin@sistema.com |
Admin@1234 |
| Usuário comum | Cadastre via /register |
— |
| Método | Rota | Acesso | Descrição |
|---|---|---|---|
GET |
/ |
Público | Redireciona para /login |
GET |
/login |
Público | Página de login |
POST |
/login |
Público | Processa autenticação |
GET |
/register |
Público | Formulário de cadastro |
POST |
/register |
Público | Processa cadastro |
POST |
/logout |
Autenticado | Encerra sessão |
GET |
/home |
ROLE_USER |
Home do usuário comum |
GET |
/admin/home |
ROLE_ADMIN |
Painel do administrador |
GET |
/h2-console/** |
Público (dev) | Console do banco H2 |
URL: http://localhost:8080/h2-console
JDBC URL: jdbc:h2:file:./data/authdb
Usuário: sa
Senha: (vazio)
Desabilitar em produção:
spring.h2.console.enabled=false
src/
└── main/
├── java/com/seuprojeto/authsystem/
│ ├── config/
│ │ ├── SecurityConfig.java ← Configuração central do Spring Security
│ │ └── DataInitializer.java ← Seed do admin padrão
│ ├── controller/
│ │ ├── AuthController.java ← Login e cadastro
│ │ └── HomeController.java ← Páginas home por role
│ ├── dto/
│ │ └── UserRegistrationDto.java ← DTO do formulário de cadastro
│ ├── model/
│ │ ├── User.java ← Entidade JPA
│ │ └── Role.java ← Enum de roles
│ ├── repository/
│ │ └── UserRepository.java ← Acesso a dados
│ └── service/
│ ├── UserService.java ← Interface de negócio
│ ├── UserServiceImpl.java ← Implementação com BCrypt
│ └── CustomUserDetailsService ← Bridge com Spring Security
└── resources/
├── application.properties
├── static/css/style.css
└── templates/
├── auth/
│ ├── login.html
│ └── register.html
└── home/
├── user-home.html
└── admin-home.html
# Todos os testes
.\mvnw.cmd test
# Resultado esperado
# Tests run: 20, Failures: 0, Errors: 0, Skipped: 0
# BUILD SUCCESS| Categoria | Testes | O que valida |
|---|---|---|
| Contexto | 1 | Aplicação sobe sem erros |
| Páginas públicas | 2 | /login e /register retornam 200 sem autenticação |
| Proteção de rotas | 2 | /home e /admin/home redirecionam sem autenticação |
| Login válido | 2 | Usuário e admin autenticam com credenciais corretas |
| Login inválido | 2 | Senha errada e e-mail inexistente retornam unauthenticated |
| Controle de acesso | 4 | Roles corretas acessam; roles erradas recebem 403 |
| Cadastro | 4 | Dados válidos, e-mail duplicado, senhas divergentes, campos vazios |
| Logout | 1 | Sessão destruída e redirecionamento correto |
| CSRF | 1 | POST sem token retorna 403 |
| Segurança de senha | 1 | Hash BCrypt $2a$12$ no banco, nunca texto puro |
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>spring.datasource.url=${DB_URL}
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}
spring.h2.console.enabled=false
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
server.servlet.session.cookie.secure=true$env:DB_URL = "jdbc:postgresql://localhost:5432/authdb"
$env:DB_USER = "postgres"
$env:DB_PASSWORD = "SuaSenhaSegura"
$env:ADMIN_EMAIL = "admin@suaempresa.com"
$env:ADMIN_PASSWORD = "SenhaAdminForte#2026"- HTTPS obrigatório — Configurar
server.ssl.*ou proxy reverso (Nginx/Caddy) - Rate limiting no login — Adicionar
Bucket4jpara bloquear brute force (ex: máx. 5 tentativas/minuto por IP) - Troca de senha obrigatória no 1º login do admin — Detectar credencial padrão e forçar troca
- Variáveis de ambiente para credenciais do admin — Substituir constantes em
DataInitializerpor@Value - Desabilitar H2 Console em produção —
spring.h2.console.enabled=falseno profile de prod
- Migrar para JWT — Estrutura já preparada (
AuthenticationManagerexposto); substituir sessões por tokens stateless - Auditoria de login — Criar tabela
login_events(IP, timestamp, sucesso/falha) para detectar anomalias - Profiles Spring (
application-dev.properties,application-prod.properties) — Separar configurações por ambiente - Flyway ou Liquibase — Versionamento de schema do banco em vez de
ddl-auto - Paginação de usuários no painel admin —
PageablenoUserRepository - Perfil do usuário — Endpoints para alterar nome e senha (com confirmação da senha atual)
- Testes de cobertura — Adicionar JaCoCo com meta mínima de 80% nas camadas
serviceecontroller
- Remember Me —
rememberMe()noSecurityConfigcom token persistido no banco - Recuperação de senha por e-mail — Fluxo de reset com token temporário (Spring Mail)
- OAuth2 / Login social — Google ou GitHub via
spring-boot-starter-oauth2-client - Internacionalização —
messages.propertiespara centralizar mensagens de validação e erro - Docker —
Dockerfile+docker-compose.ymlcom PostgreSQL para ambiente reproduzível - CI/CD — GitHub Actions rodando
mvn testem todo Pull Request
H2 file (jdbc:h2:file:) persiste os dados entre reinicializações durante o desenvolvimento, simulando melhor o comportamento de produção. In-memory (jdbc:h2:mem:) perde os dados a cada restart.
Strength 12 gera ~400ms por operação de hash — aceitável para o usuário no login, mas exponencialmente mais custoso para ataques de força bruta comparado ao default 10.
Responsabilidade única: CustomUserDetailsService cuida exclusivamente de autenticação. UserServiceImpl cuida de regras de negócio. Essa separação facilita a futura migração para JWT sem reescrever a lógica de negócio.
Usar a entidade User em formulários expõe o campo role a manipulação externa (mass assignment). O DTO define exatamente quais campos o usuário pode preencher.
Um link <a href="/logout"> é um GET — qualquer site externo pode forçar o logout do usuário. O POST com token CSRF garante que apenas o próprio sistema pode disparar o logout.
MIT — veja o arquivo LICENSE para detalhes.