Skip to Content

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 des Entrées

Ne jamais faire confiance aux données utilisateur !

Principe : Valider toutes les entrées avant de les traiter.

CoucheResponsabilitéValidation
InfrastructureValidation format HTTP@NotBlank, @Size, @Pattern
ApplicationValidation règles métierUse case vérifie la logique
DomainInvariants métierConstructeurs 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

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

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.

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 !

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.

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

  1. Validation : Valider TOUTES les entrées (DTO + Value Objects)
  2. Sanitization : Paramètres préparés (SQL), échapper HTML
  3. Authentication : BCrypt + JWT avec expiration
  4. Authorization : @Secured + vérifications métier
  5. Secrets : Variables d’environnement (jamais hardcodés)
  6. HTTPS : Toujours en production
  7. Rate limiting : Protéger les endpoints sensibles

OWASP Top 10

VulnérabilitéSolution
1. InjectionParamètres préparés
2. Broken AuthBCrypt + JWT
3. Sensitive DataMasquer dans logs/DTOs
4. MisconfigurationCORS 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.

Last updated on