Une API REST complète avec authentification JWT, gestion des rôles (USER/ADMIN) et opérations CRUD sur les entités Users et Products.
- Framework: Spring Boot 3.4.5
- Base de données: MongoDB
- Authentification: JWT (JSON Web Token)
- Sécurité: Spring Security
- Validation: Spring Validation
- Build: Maven
- Java: 17
- Rate Limiting: Bucket4j
- SSL: HTTPS avec certificat PKCS12
- Conteneurisation: Docker & Docker Compose
- Java 17+
- Maven 3.6+
- Docker & Docker Compose (recommandé)
- Un outil de test API (Postman, curl, etc.)
Le projet inclut un fichier docker-compose.yaml pour faciliter le déploiement de MongoDB :
# Démarrer MongoDB et Mongo Express avec Docker Compose
docker-compose up -dCette commande démarre :
- MongoDB sur le port
27017 - Mongo Express (interface web) sur le port
8081
- URL:
http://localhost:8081 - Identifiants: root / rootpassword
L'API utilise HTTPS avec redirection automatique HTTP → HTTPS :
- Port HTTPS : 8443 (principal)
- Port HTTP : 8080 (redirection automatique vers HTTPS)
Un certificat keystore.p12 est requis dans le répertoire src/main/resources/.
Modifiez application.properties selon votre configuration :
# Base de données MongoDB
spring.data.mongodb.uri=mongodb://root:rootpassword@localhost:27017/letsplay?authSource=admin
spring.data.mongodb.database=letsplay
# Serveur HTTPS
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=admin123
# JWT Secret (à modifier en production)
jwt.secret=votre_secret_jwt_ici- Cloner le projet
git clone https://learn.zone01dakar.sn/git/preydedy/lets-play
cd letsplay- Démarrer MongoDB
docker-compose up -d- Installer les dépendances et démarrer l'application
mvn clean install
mvn spring-boot:run- Installer MongoDB localement
- Configurer les paramètres de connexion
- Démarrer l'application
L'API sera accessible sur : https://localhost:8443/api
Les requêtes HTTP sur le port 8080 seront automatiquement redirigées vers HTTPS (port 8443).
Au démarrage de l'application, un compte administrateur par défaut est créé automatiquement :
{
"name": "adminroot",
"email": "admin@root.com",
"password": "test123",
"role": "ADMIN"
}L'API inclut une protection contre les attaques par force brute :
- Endpoint protégé :
/api/auth/login - Limite : 5 tentatives par minute par adresse IP
- Réponse : Code 429 "Trop de tentatives. Réessayez plus tard."
CORS configuré pour accepter les requêtes depuis http://localhost:4200 (frontend Angular).
Le token JWT contient les informations suivantes :
- ID utilisateur
- Rôle (USER/ADMIN)
- Date d'expiration
- Inscription/Connexion pour obtenir un token
- Inclure le token dans l'en-tête
Authorization: Bearer <token>pour les endpoints protégés
POST /api/auth/register
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com",
"password": "motdepasse123",
"role": "USER"
}Réponse (201 Created):
{
"id": "60f7b3b3b3b3b3b3b3b3b3b3",
"name": "John Doe",
"email": "john@example.com",
"role": "USER"
}POST /api/auth/login
Content-Type: application/json
{
"email": "john@example.com",
"password": "motdepasse123"
}Réponse (200 OK):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}GET /api/users/{id}
Authorization: Bearer <token>Autorisations: Propriétaire ou ADMIN
Réponse (200 OK):
{
"id": "60f7b3b3b3b3b3b3b3b3b3b3",
"name": "John Doe",
"email": "john@example.com",
"role": "USER"
}PUT /api/users/{id}
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "John Smith",
"email": "johnsmith@example.com",
"password": "nouveaumotdepasse123"
}Autorisations: Propriétaire ou ADMIN
GET /api/productsAutorisations: Public (aucune authentification requise)
Réponse (200 OK):
[
{
"id": "60f7b3b3b3b3b3b3b3b3b3b3",
"name": "Produit 1",
"description": "Description du produit 1",
"price": 29.99,
"userId": "60f7b3b3b3b3b3b3b3b3b3b3"
}
]GET /api/products/{id}Autorisations: Public
POST /api/products
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "Nouveau produit",
"description": "Description du nouveau produit",
"price": 49.99
}Autorisations: USER ou ADMIN
Réponse (200 OK):
{
"id": "60f7b3b3b3b3b3b3b3b3b3b3",
"name": "Nouveau produit",
"description": "Description du nouveau produit",
"price": 49.99,
"userId": "60f7b3b3b3b3b3b3b3b3b3b3"
}PUT /api/products/{id}
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "Produit modifié",
"description": "Description modifiée",
"price": 59.99
}Autorisations: Propriétaire du produit ou ADMIN
Toutes les routes administratives nécessitent le rôle ADMIN
GET /api/admin/users
Authorization: Bearer <token>DELETE /api/admin/users/{id}
Authorization: Bearer <token>Réponse: 204 No Content
DELETE /api/admin/products/{id}
Authorization: Bearer <token>Réponse: 204 No Content
| Endpoint | Public | USER | ADMIN | Propriétaire |
|---|---|---|---|---|
GET /products |
✅ | ✅ | ✅ | ✅ |
GET /products/{id} |
✅ | ✅ | ✅ | ✅ |
POST /products |
❌ | ✅ | ✅ | - |
PUT /products/{id} |
❌ | ❌ | ✅ | ✅ |
GET /users/{id} |
❌ | ❌ | ✅ | ✅ |
PUT /users/{id} |
❌ | ❌ | ✅ | ✅ |
GET /admin/users |
❌ | ❌ | ✅ | - |
DELETE /admin/users/{id} |
❌ | ❌ | ✅ | - |
DELETE /admin/products/{id} |
❌ | ❌ | ✅ | - |
- Rate Limiting: Protection contre les attaques par déni de service (5 req/min sur login)
- Redirection HTTPS: Toutes les requêtes HTTP sont automatiquement redirigées vers HTTPS
- Validation des données: Sanitisation des entrées utilisateur
- Chiffrement des mots de passe: BCrypt
- HTTPS: Communication sécurisée avec certificat PKCS12
- JWT: Tokens sécurisés avec expiration
- CORS: Configuration sécurisée pour les appels cross-origin
{
"id": "string",
"name": "string",
"email": "string",
"password": "string (chiffré)",
"role": "USER|ADMIN"
}{
"id": "string",
"name": "string",
"description": "string",
"price": "number",
"userId": "string"
}L'API utilise un GlobalExceptionHandler qui gère automatiquement :
- Validation :
MethodArgumentNotValidException→ 400 Bad Request - Authentification :
UsernameNotFoundException,BadCredentialsException,JwtException→ 401 Unauthorized - Autorisation :
AccessDeniedException→ 403 Forbidden - Ressource non trouvée :
NoHandlerFoundException,ResourceNotFoundException→ 404 Not Found - Conflits :
EmailAlreadyUsedException→ 409 Conflict - Mots de passe faibles :
PasswordTooWeakException,InvalidException→ 400 Bad Request - Erreurs génériques :
Exception→ 500 Internal Server Error
- 200: Succès
- 201: Créé avec succès
- 204: Suppression réussie
- 400: Données invalides
- 401: Non authentifié
- 403: Accès refusé
- 404: Ressource non trouvée
- 409: Conflit (ex: email déjà utilisé)
- 429: Trop de requêtes (Rate limiting)
- 500: Erreur serveur
{
"status": 400,
"error": "Bad Request",
"message": "Description de l'erreur",
"path": "/api/endpoint"
}- Email déjà utilisé:
EmailAlreadyUsedException - Mot de passe trop faible:
PasswordTooWeakException - Ressource non trouvée:
ResourceNotFoundException - ID invalide:
InvalidException - Token JWT invalide:
JwtException - Trop de tentatives de connexion: Rate limiting (429)
Une collection Postman est fournie : CRUD_API_JWT_Postman_Collection.json
{
"base_url": "https://localhost:8443/api",
"jwt_token": "{{token_obtenu_lors_du_login}}",
"user_id": "{{id_utilisateur}}",
"product_id": "{{id_produit}}"
}- Connexion administrateur avec les identifiants par défaut
- Inscription d'un nouvel utilisateur
- Connexion pour obtenir le token JWT
- Créer des produits avec le token
- Tester les différents endpoints selon les rôles
- Tester le rate limiting sur
/api/auth/login
Le projet inclut un docker-compose.yaml qui configure :
services:
mongo:
image: mongo:latest
ports: ["27017:27017"]
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: rootpassword
volumes:
- mongo_data:/data/db
mongo-express:
image: mongo-express
ports: ["8081:8081"]
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: rootpassword# Démarrer les services
docker-compose up -d
# Arrêter les services
docker-compose down
# Voir les logs
docker-compose logs -f
# Supprimer les volumes (attention : perte de données)
docker-compose down -vsrc/main/java/com/example/letsplay/
├── controller/ # Contrôleurs REST
├── dto/ # Objets de transfert de données
├── exception/ # Gestion des exceptions
├── model/ # Entités MongoDB
├── repository/ # Repositories MongoDB
├── security/ # Configuration sécurité & JWT
├── service/ # Logique métier
└── AdminInitializer.java # Initialisation admin
La classe SecurityConfig configure :
- Filtres JWT : Authentification par token
- Autorisations : Règles d'accès par rôle
- CORS : Configuration cross-origin
- Providers : Authentification et encodage des mots de passe
- Créer les DTOs appropriés
- Ajouter les validations nécessaires
- Implémenter la logique dans les services
- Créer les endpoints dans les contrôleurs
- Configurer les autorisations dans SecurityConfig
- Ajouter la gestion d'erreurs dans GlobalExceptionHandler
- Ajouter les tests correspondants
Utilisateurs:
- Nom : obligatoire, non vide
- Email : format valide, unique, 5-50 caractères
- Mot de passe : minimum 6 caractères
- Rôle : "USER" ou "ADMIN"
Produits:
- Nom : obligatoire, non vide
- Description : obligatoire, non vide
- Prix : positif, minimum 0
- Sanitisation: Protection contre l'injection MongoDB
- Anti-XSS: Filtrage des scripts malveillants
- Longueur: Limitation à 255 caractères par champ
- Rate Limiting: Protection contre les attaques par force brute
- Initialisation admin : "✅ Admin user created"
- Rate limiting : "Trop de tentatives. Réessayez plus tard."
- Redirection HTTPS : Vérifiez les logs Tomcat
- Certificat SSL manquant : Vérifiez
keystore.p12dansresources/ - MongoDB inaccessible : Vérifiez Docker Compose
- Rate limiting déclenché : Attendez 1 minute entre les tentatives
- CORS bloqué : Vérifiez l'origine dans SecurityConfig
Pour toute question ou problème :
- Vérifiez les logs de l'application
- Consultez la documentation des erreurs
- Testez avec la collection Postman fournie
- Vérifiez l'état des conteneurs Docker
- Changez le secret JWT dans
application.properties - Changez le mot de passe admin par défaut
- Utilisez des certificats SSL valides (Let's Encrypt)
- Configurez MongoDB avec authentification forte
- Activez les logs de sécurité et monitoring
- Configurez un reverse proxy (Nginx/Apache)
- Mettez en place un monitoring des performances
- Configurez des sauvegardes MongoDB automatiques
- Ajustez les limites de rate limiting selon vos besoins
- Utilisez des variables d'environnement pour les secrets
JWT_SECRET=your_super_secure_jwt_secret_here
MONGO_URI=mongodb://user:password@localhost:27017/letsplay
SSL_KEYSTORE_PASSWORD=your_keystore_password
ADMIN_DEFAULT_PASSWORD=your_secure_admin_passwordThis project is licensed under the MIT License - see the LICENSE file for details.