Sécurité
Protégez votre application contre les vulnérabilités et les attaques avec des pratiques de sécurité robustes.
La sécurité n’est pas optionnelle ! Une faille de sécurité peut compromettre toute votre application.
Les 3 Piliers de la Sécurité
🛡️ Validation
Validation des Entrées
Ne jamais faire confiance aux données utilisateur !
Principe : Valider toutes les entrées avant de les traiter.
| Couche | Responsabilité | Validation |
|---|---|---|
| Infrastructure | Validation format HTTP | @NotBlank, @Size, @Pattern |
| Application | Validation règles métier | Use case vérifie la logique |
| Domain | Invariants métier | Constructeurs des Value Objects |
Exemple complet :
// 1. Infrastructure : Validation format
@Controller("/api/users")
public class UserController {
@Post
public UserResponse createUser(
@Body @Valid UserRequest request // ← @Valid déclenche la validation
) {
// Si validation échoue, 400 Bad Request automatique
}
}
// 2. DTO avec annotations de validation
@Data
public class UserRequest {
@NotBlank(message = "Email cannot be empty")
@Email(message = "Email must be valid")
private String email;
@NotBlank(message = "Password cannot be empty")
@Size(min = 8, max = 100, message = "Password must be 8-100 characters")
@Pattern(
regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).*$",
message = "Password must contain lowercase, uppercase and digit"
)
private String password;
}
// 3. Domain : Value Object avec validation métier
@Value
public class Email {
String value;
public Email(String value) {
if (value == null || !value.matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
throw new IllegalArgumentException("Invalid email format");
}
if (isDisposableEmail(value)) {
throw new IllegalArgumentException("Disposable emails are not allowed");
}
this.value = value.toLowerCase();
}
private boolean isDisposableEmail(String email) {
// Logique métier : bloquer les emails jetables
return email.endsWith("@tempmail.com");
}
}Avantages :
- ✅ Validation en couches (défense en profondeur)
- ✅ Erreurs claires pour l’utilisateur
- ✅ Impossible de créer des objets invalides
OWASP Top 10 et Architecture Hexagonale
L’OWASP Top 10 liste les 10 vulnérabilités les plus critiques.
1. Injection
❌ Vulnérable
Code Vulnérable
// ❌ Injection SQL
@Singleton
public class TrendRepositoryAdapter implements TrendRepository {
@Override
public List<TrendResult> search(String keyword) {
String sql = "SELECT * FROM trends WHERE keyword = '" + keyword + "'";
return jdbcTemplate.query(sql, rowMapper);
// keyword = "'; DELETE FROM trends; --" = CATASTROPHE
}
}2. Broken Authentication
❌ Faible
Authentication Faible
// ❌ DANGEREUX : Mots de passe en clair
@Singleton
public class UserService {
public boolean authenticate(String email, String password) {
User user = userRepository.findByEmail(email);
return user.getPassword().equals(password); // ❌ Clair !
}
}
// ❌ DANGEREUX : Session jamais expirée
@Controller
public class SessionController {
@Post("/login")
public void login() {
session.put("userId", userId);
// Pas d'expiration = session infinie !
}
}3. Sensitive Data Exposure
Ne jamais exposer de données sensibles (mots de passe, tokens, clés API) dans les logs, réponses HTTP, ou exceptions.
❌ Exposé
Données Exposées
// ❌ DANGEREUX : Password dans les logs
@Controller
public class AuthController {
@Post("/login")
public void login(@Body LoginRequest request) {
log.info("Login attempt: {}", request);
// Log: Login attempt: LoginRequest(email=user@example.com, password=secret123)
// ❌ Password en clair dans les logs !
}
}
// ❌ DANGEREUX : Password dans la réponse
@Data
public class UserResponse {
private String email;
private String passwordHash; // ❌ Ne doit JAMAIS être exposé !
}4. Security Misconfiguration
Configurations par défaut = souvent non sécurisées !
❌ Non Sécurisé
Configuration Non Sécurisée
# application.yml
micronaut:
server:
cors:
enabled: true
configurations:
web:
allowed-origins:
- "*" # ❌ Accepte TOUS les domaines (CSRF, XSS)
security:
enabled: false # ❌ Sécurité désactivée// ❌ Secrets hardcodés
public class ApiClient {
private static final String API_KEY = "sk_live_abc123"; // ❌ En clair dans le code !
}5. Broken Access Control
Vérifier les permissions pour chaque action sensible.
❌ Sans Contrôle
Pas de Contrôle d’Accès
// ❌ DANGEREUX : N'importe qui peut supprimer n'importe quel utilisateur
@Controller("/api/users")
public class UserController {
@Delete("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.delete(id);
// ❌ Pas de vérification : utilisateur A peut supprimer utilisateur B !
}
}Sécurité par Couche
Checklist Sécurité
Validation des Entrées
- Toutes les entrées utilisateur sont validées (
@Valid,@NotBlank, etc.) - Value Objects avec validation dans les constructeurs
- Rejet des caractères dangereux (SQL, XSS, command injection)
Sanitization
- Paramètres préparés pour les requêtes SQL (pas de concaténation)
- Échapper le HTML dans les sorties (
htmlEscape()) - Valider les chemins de fichiers (path traversal)
Authentication & Authorization
- Mots de passe hashés avec BCrypt (jamais en clair)
- JWT avec expiration (1h-24h max)
- Endpoints protégés avec
@Secured - Vérification des permissions pour les actions sensibles
Configuration
- CORS limité aux domaines autorisés (pas
*) - Secrets dans variables d’environnement (pas hardcodés)
- HTTPS activé en production
- Headers de sécurité (CSP, X-Frame-Options, etc.)
Données Sensibles
- Jamais de passwords/tokens dans les logs
- Jamais de données sensibles dans les DTOs de réponse
-
@JsonProperty(access = WRITE_ONLY)pour les champs sensibles
Monitoring
- Logs des tentatives de connexion échouées
- Alertes sur les activités suspectes
- Rate limiting pour éviter le brute force
Headers de Sécurité HTTP
Micronaut permet de configurer facilement les headers de sécurité.
# application.yml
micronaut:
server:
cors:
enabled: true
configurations:
web:
allowed-origins:
- "https://myapp.com"
security:
enabled: true
http:
headers:
# Empêcher le clickjacking
x-frame-options: DENY
# Forcer HTTPS
strict-transport-security: max-age=31536000; includeSubDomains
# Empêcher le MIME sniffing
x-content-type-options: nosniff
# Activer le filtre XSS du navigateur
x-xss-protection: 1; mode=block
# Content Security Policy
content-security-policy: "default-src 'self'; script-src 'self'; style-src 'self'"Tester les headers :
curl -I https://myapp.com/api/health
HTTP/2 200
x-frame-options: DENY
strict-transport-security: max-age=31536000; includeSubDomains
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
content-security-policy: default-src 'self'Rate Limiting
Protégez vos endpoints contre le brute force et les attaques DoS.
// Custom Rate Limiter
@Singleton
public class RateLimitFilter implements HttpServerFilter {
private final LoadingCache<String, AtomicInteger> requestCounts = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.build(key -> new AtomicInteger(0));
@Override
public Publisher<MutableHttpResponse<?>> doFilter(
HttpRequest<?> request,
ServerFilterChain chain
) {
String clientIp = request.getRemoteAddress().getAddress().getHostAddress();
AtomicInteger count = requestCounts.get(clientIp);
if (count.incrementAndGet() > 100) { // Max 100 requêtes/minute
return Publishers.just(
HttpResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.body("Rate limit exceeded")
);
}
return chain.proceed(request);
}
}Configuration pour un endpoint spécifique :
@Controller("/api/auth")
public class AuthController {
@Post("/login")
@RateLimit(value = 5, duration = "1m") // Max 5 tentatives/minute
public HttpResponse<?> login(@Body LoginRequest request) {
// ...
}
}Récapitulatif
Sécurité = Validation + Sanitization + Authentication + Configuration
Règles d’Or
- Validation : Valider TOUTES les entrées (DTO + Value Objects)
- Sanitization : Paramètres préparés (SQL), échapper HTML
- Authentication : BCrypt + JWT avec expiration
- Authorization :
@Secured+ vérifications métier - Secrets : Variables d’environnement (jamais hardcodés)
- HTTPS : Toujours en production
- Rate limiting : Protéger les endpoints sensibles
OWASP Top 10
| Vulnérabilité | Solution |
|---|---|
| 1. Injection | Paramètres préparés |
| 2. Broken Auth | BCrypt + JWT |
| 3. Sensitive Data | Masquer dans logs/DTOs |
| 4. Misconfiguration | CORS strict, secrets en env vars |
| 5. Access Control | @Secured + règles métier |
Prochaines Étapes
Votre application est maintenant sécurisée ! Passez aux patterns avancés.
- 📖 Adaptateurs Multiples - Cache, fallback, decorator
- 📖 Event-Driven - Architecture événementielle
- 📖 Code Propre - SOLID et bonnes pratiques
- 📖 Performance - Optimisations Micronaut