Um sistema de chat em tempo real com criptografia de ponta a ponta, desenvolvido com Spring Boot e WebSocket.
Desenvolvido por: @vitinh0z
Chat0z é uma aplicação de mensagens instantâneas que permite aos usuários criar salas de chat privadas e se comunicar em tempo real com segurança. Todas as mensagens são criptografadas usando AES-256, garantindo que apenas membros da sala possam ler o conteúdo das conversas.
- 🔐 Autenticação OAuth2 com Google
- 💬 Chat em tempo real usando WebSocket (STOMP)
- 🔒 Criptografia AES-256 de mensagens
- 🚪 Sistema de salas com códigos de convite únicos
- 👥 Sistema de permissões (Dono, Admin, Membro)
- 📝 Gerenciamento de mensagens (enviar, deletar)
- 👤 Perfis de usuário com status (ONLINE, OFFLINE, BUSY)
- 🎯 Sistema de membros para controle de acesso às salas
- Java 21 - Linguagem de programação
- Spring Boot 4.0.1 - Framework principal
- Spring Security - Autenticação e autorização
- Spring WebSocket - Comunicação em tempo real
- Spring Data JPA - Persistência de dados
- Lombok - Redução de código boilerplate
- H2 Database - Banco em memória (desenvolvimento)
- PostgreSQL - Banco de dados (produção - suportado)
- OAuth2 Client - Autenticação com Google
- AES/CBC/PKCS5Padding - Criptografia de mensagens
- SHA-256 - Geração de chaves a partir dos códigos de convite
- Maven - Gerenciamento de dependências
- JUnit - Testes unitários
Antes de começar, certifique-se de ter instalado:
- Java JDK 21 ou superior
- Maven 3.8+ (ou use o wrapper incluído:
./mvnw) - Git para clonar o repositório
Para autenticação OAuth2 com Google, você precisará:
- Criar um projeto no Google Cloud Console
- Configurar credenciais OAuth2
- Obter
Client IDeClient Secret
git clone https://github.com/vitinh0z/Chat0z.git
cd Chat0zCrie as seguintes variáveis de ambiente ou edite application.properties:
export GOOGLE_CLIENT_ID=seu-client-id-aqui
export GOOGLE_CLIENT_SECRET=seu-client-secret-aquiOu edite src/main/resources/application.properties:
spring.security.oauth2.client.registration.google.client-id=SEU_CLIENT_ID
spring.security.oauth2.client.registration.google.client-secret=SEU_CLIENT_SECRET./mvnw clean installOu no Windows:
mvnw.cmd clean install./mvnw spring-boot:runA aplicação estará disponível em: http://localhost:8080
Chat0z/
├── src/
│ ├── main/
│ │ ├── java/io/github/vitinh0z/chat/
│ │ │ ├── config/ # Configurações (WebSocket, Security)
│ │ │ ├── controller/ # Controllers REST e WebSocket
│ │ │ │ ├── chat/ # ChatController (WebSocket)
│ │ │ │ ├── message/ # MessageController
│ │ │ │ ├── room/ # RoomController
│ │ │ │ └── user/ # UserController
│ │ │ ├── dto/ # Data Transfer Objects
│ │ │ ├── entities/ # Entidades JPA
│ │ │ │ ├── membership/ # Membership (relacionamento User-Room)
│ │ │ │ ├── message/ # Message
│ │ │ │ ├── room/ # Room
│ │ │ │ └── user/ # User
│ │ │ ├── enums/ # Enumerações (UserStatus, RoomRole)
│ │ │ ├── repository/ # Repositórios JPA
│ │ │ ├── service/ # Lógica de negócio
│ │ │ └── utils/ # Utilitários (CryptoUtils)
│ │ └── resources/
│ │ └── application.properties
│ └── test/ # Testes unitários
├── pom.xml # Configuração Maven
└── README.md
| Método | Endpoint | Descrição | Autenticação |
|---|---|---|---|
| GET | /user/me |
Retorna dados do usuário autenticado | Obrigatória |
| PUT | /user/update |
Atualiza informações do usuário | Obrigatória |
| PUT | /user/status |
Atualiza status do usuário | Obrigatória |
| Método | Endpoint | Descrição | Autenticação |
|---|---|---|---|
| GET | /room/me |
Lista todas as salas do usuário | Obrigatória |
| POST | /room/create |
Cria uma nova sala | Obrigatória |
| POST | /room/enter |
Entra em uma sala com código de convite | Obrigatória |
Exemplo de criação de sala:
POST /room/create
{
"id": 1,
"name": "Sala dos Devs",
"invite": "codigo-secreto-123"
}Exemplo de entrada em sala:
POST /room/enter
{
"inviteCode": "codigo-secreto-123"
}| Método | Endpoint | Descrição | Autenticação |
|---|---|---|---|
| GET | /message/all/{roomId} |
Busca todas as mensagens de uma sala | Obrigatória |
A aplicação usa STOMP over WebSocket para comunicação em tempo real.
const socket = new SockJS('http://localhost:8080/connect');
const stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
console.log('Conectado: ' + frame);
// Inscrever-se em uma sala
stompClient.subscribe('/topic/room/1', function(message) {
const msg = JSON.parse(message.body);
console.log('Nova mensagem:', msg);
});
});stompClient.send("/app/chat/1", {}, JSON.stringify({
'userId': 1,
'content': 'Olá, mundo!'
}));stompClient.send("/app/chat/1/delete", {}, JSON.stringify({
'userId': 1,
'messageId': 123
}));| Destino | Descrição | Subscrição |
|---|---|---|
/app/chat/{roomId} |
Enviar mensagem para uma sala | /topic/room/{roomId} |
/app/chat/{roomId}/delete |
Deletar mensagem de uma sala | /topic/room/{roomId} |
O Chat0z usa OAuth2 com Google para autenticação. O fluxo é:
- Usuário clica em "Login com Google"
- Redirecionado para autorização do Google
- Após aprovação, retorna com token OAuth2
- Sistema cria/atualiza o usuário no banco
- Sessão autenticada é criada
Todas as mensagens são criptografadas usando AES-256 em modo CBC:
- Chave de criptografia: Gerada a partir do código de convite da sala usando SHA-256
- Vetor de inicialização (IV): Gerado aleatoriamente para cada mensagem
- Formato:
Base64(IV + Mensagem Criptografada)
Características:
- Cada sala tem sua própria chave (derivada do código de convite)
- Apenas membros da sala podem descriptografar as mensagens
- IV aleatório garante que mensagens idênticas tenham criptografias diferentes
// Exemplo de uso (já implementado no MessageService)
String encrypted = CryptoUtils.encrypt("Olá!", "codigo-convite");
String decrypted = CryptoUtils.decrypt(encrypted, "codigo-convite");Existem 3 níveis de permissão nas salas:
| Papel | Permissões |
|---|---|
| OWNER | Pode deletar qualquer mensagem, gerenciar admins, deletar a sala |
| ADMIN | Pode deletar qualquer mensagem, gerenciar membros |
| MEMBER | Pode apenas deletar suas próprias mensagens |
- id: Long
- nickname: String
- email: String (único)
- picProfile: String
- userStatus: UserStatus (ONLINE, OFFLINE, BUSY)
- roomsCreated: List<Room>
- participating: List<Membership>- id: Long
- roomName: String
- password: String
- inviteCode: String (único)
- owner: User
- memberships: List<Membership>
- messages: List<Message>- id: Long
- content: String (criptografado)
- user: User
- room: Room
- timestamp: LocalDateTime- id: Long
- user: User
- room: Room
- roomRole: RoomRole (OWNER, ADMIN, MEMBER)./mvnw testPara executar um teste específico:
./mvnw test -Dtest=MessageServiceTestPara ver cobertura de testes:
./mvnw verifyEdite application.properties:
# Comentar/remover configurações do H2
# spring.datasource.url=jdbc:h2:mem:testdb
# Adicionar configurações do PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/chatoz
spring.datasource.username=seu-usuario
spring.datasource.password=sua-senha
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=updateserver.port=3000logging.level.io.github.vitinh0z.chat=DEBUG
logging.level.org.springframework.security=DEBUG
logging.level.org.springframework.messaging=DEBUG- Acesse
http://localhost:8080 - Clique em "Login com Google"
- Autorize a aplicação
POST /room/create
{
"id": 1,
"name": "Minha Sala Privada",
"invite": "sala-secreta-xyz"
}- Compartilhe o código
sala-secreta-xyzcom seus amigos
POST /room/enter
{
"inviteCode": "sala-secreta-xyz"
}// Conectar
const socket = new SockJS('http://localhost:8080/connect');
const stompClient = Stomp.over(socket);
// Inscrever-se na sala
stompClient.subscribe('/topic/room/1', function(message) {
console.log('Mensagem recebida:', JSON.parse(message.body));
});
// Enviar mensagem
stompClient.send("/app/chat/1", {}, JSON.stringify({
'userId': 1,
'content': 'Olá, pessoal!'
}));Solução: Configure as variáveis de ambiente ou edite application.properties com suas credenciais OAuth2.
Solução: Altere a porta em application.properties:
server.port=8081Solução: Isso significa que a chave de descriptografia está incorreta. Verifique se você está usando o mesmo código de convite que foi usado para criar a sala.
Solução: Certifique-se de que:
- A aplicação está rodando
- Você está usando o endpoint correto:
/connect - O CORS está configurado corretamente se estiver acessando de outro domínio
Funcionalidades planejadas para versões futuras:
- Interface web completa (frontend)
- Suporte para arquivos e imagens
- Mensagens de áudio
- Notificações em tempo real
- Indicador de "digitando..."
- Reações a mensagens
- Responder mensagens (threads)
- Busca de mensagens
- Temas claro/escuro
- Aplicativo mobile
Contribuições são bem-vindas! Sinta-se livre para:
- Fazer fork do projeto
- Criar uma branch para sua feature (
git checkout -b feature/MinhaFeature) - Commit suas mudanças (
git commit -m 'Adiciona MinhaFeature') - Push para a branch (
git push origin feature/MinhaFeature) - Abrir um Pull Request
Por favor, mantenha o código limpo e siga as convenções do projeto.
Este projeto é de código aberto e está disponível para uso livre.
Importante: Se você usar este código ou partes dele em seus projetos, por favor mantenha os créditos ao desenvolvedor original.
Desenvolvedor: Victor Gabriel (@vitinh0z)
Este projeto foi desenvolvido como um sistema de chat completo e seguro, utilizando as melhores práticas de desenvolvimento Spring Boot.
Para dúvidas, sugestões ou reportar problemas:
- GitHub: @vitinh0z
- Issues: Reportar um problema
Se este projeto foi útil para você, considere dar uma ⭐ no repositório!
Desenvolvido com ❤️ por @vitinh0z