Contactez-nous

Configuration de HTTPS/SSL

Sécurisez votre application Spring Boot en activant HTTPS/SSL. Apprenez à configurer les certificats et les keystores pour un chiffrement robuste des communications.

Pourquoi sécuriser votre application avec HTTPS ?

A l'ère numérique actuelle, la sécurité des applications web n'est plus une option, mais une nécessité absolue. Le protocole HTTP standard transmet les données en clair entre le navigateur du client et le serveur, les rendant vulnérables à l'interception et à la modification (attaques de type "Man-in-the-Middle"). HTTPS (HyperText Transfer Protocol Secure) résout ce problème en ajoutant une couche de chiffrement via les protocoles SSL (Secure Sockets Layer) ou, plus couramment aujourd'hui, TLS (Transport Layer Security).

L'activation de HTTPS offre plusieurs avantages cruciaux :

  • Confidentialité : Les données échangées (identifiants, informations personnelles, données métier) sont chiffrées et ne peuvent pas être lues par des tiers non autorisés.
  • Intégrité : Le chiffrement garantit que les données n'ont pas été altérées pendant leur transit.
  • Authentification : Le certificat SSL/TLS permet au client de vérifier l'identité du serveur auquel il se connecte, prévenant ainsi les attaques de phishing ou d'usurpation d'identité du serveur.
  • Confiance utilisateur : Les navigateurs modernes signalent clairement les sites non sécurisés (HTTP), érodant la confiance des utilisateurs. Un cadenas vert ou une indication similaire rassure les visiteurs.
  • Référencement (SEO) : Les moteurs de recherche comme Google favorisent les sites sécurisés en HTTPS dans leurs classements.

Configurer HTTPS dans votre application Spring Boot est donc une étape essentielle pour protéger vos utilisateurs, vos données et la réputation de votre service.

Certificats SSL/TLS et Keystores : les prérequis

Pour activer HTTPS, votre serveur Spring Boot a besoin d'un certificat SSL/TLS et de la clé privée correspondante. Le certificat contient la clé publique du serveur et des informations d'identification vérifiées (ou non, dans le cas des certificats auto-signés) par une Autorité de Certification (CA). La clé privée, gardée secrète par le serveur, est utilisée pour déchiffrer les informations envoyées par les clients et pour prouver l'identité du serveur lors de la négociation TLS.

Ces éléments (clé privée et certificat) sont généralement stockés dans un fichier sécurisé appelé Keystore. Spring Boot prend en charge plusieurs formats de keystores, les plus courants étant :

  • JKS (Java KeyStore) : Format historique de Java, souvent utilisé dans les applications Java plus anciennes.
  • PKCS12 (.p12, .pfx) : Un format standard plus moderne et indépendant du langage, largement utilisé et souvent fourni par les CAs. C'est le format par défaut recommandé par Spring Boot depuis la version 2.0.

Pour la production, vous obtiendrez généralement un certificat signé par une CA reconnue (comme Let's Encrypt, DigiCert, Comodo, etc.). Pour le développement et les tests locaux, vous pouvez générer un certificat auto-signé. Attention, les navigateurs afficheront un avertissement de sécurité pour les certificats auto-signés car ils ne sont pas validés par une CA de confiance.

Configuration des propriétés SSL dans Spring Boot

Spring Boot simplifie grandement la configuration de HTTPS via des propriétés dédiées dans vos fichiers `application.properties` ou `application.yml`. Les propriétés clés se trouvent sous le préfixe `server.ssl`.

Voici les propriétés essentielles à configurer :

  • `server.ssl.enabled` : Mettre à `true` pour activer SSL/TLS. (Souvent implicite si un `key-store` est fourni).
  • `server.port` : Le port standard pour HTTPS est `443`. Si vous ne configurez que HTTPS, vous devriez utiliser ce port. Sinon, vous pouvez utiliser un autre port comme `8443`.
  • `server.ssl.key-store` : Chemin d'accès au fichier keystore (ex: `classpath:keystore.p12` ou `file:/etc/ssl/keystore.jks`).
  • `server.ssl.key-store-password` : Le mot de passe pour accéder au keystore lui-même.
  • `server.ssl.key-store-type` : Le type du keystore (ex: `PKCS12`, `JKS`). Si non spécifié, Spring Boot tente de le deviner. `PKCS12` est recommandé.
  • `server.ssl.key-alias` : L'alias identifiant l'entrée clé/certificat dans le keystore. Si le keystore ne contient qu'une seule entrée, ce n'est parfois pas nécessaire, mais il est bon de le spécifier.
  • `server.ssl.key-password` : Le mot de passe protégeant la clé privée elle-même à l'intérieur du keystore. (Peut être identique au `key-store-password` mais pas obligatoirement).

Exemple de configuration (`application.properties`) :

server.port=8443
server.ssl.enabled=true
server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:certs/monkeystore.p12
server.ssl.key-store-password=MotDePasseKeystore
server.ssl.key-alias=monalias
server.ssl.key-password=MotDePasseClePrivee

Exemple de configuration (`application.yml`) :

server:
  port: 8443
  ssl:
    enabled: true
    key-store-type: PKCS12
    key-store: classpath:certs/monkeystore.p12
    key-store-password: MotDePasseKeystore
    key-alias: monalias
    key-password: MotDePasseClePrivee

Assurez-vous que le fichier keystore est accessible par l'application (par exemple, en le plaçant dans le dossier `src/main/resources` pour utiliser `classpath:` ou à un emplacement système spécifié par `file:`).

Il existe d'autres propriétés `server.ssl.*` pour une configuration plus fine, comme la définition des protocoles TLS à utiliser (`server.ssl.protocol`, `server.ssl.enabled-protocols`), des suites de chiffrement (`server.ssl.ciphers`), ou la configuration de l'authentification client (mutual TLS via `server.ssl.client-auth` et un `trust-store`).

Génération d'un certificat auto-signé pour le développement

Pour les besoins de développement ou de test local, il n'est pas toujours pratique d'obtenir un certificat signé par une CA. Vous pouvez générer facilement un certificat auto-signé et son keystore en utilisant l'outil `keytool` fourni avec le JDK.

Ouvrez un terminal ou une invite de commande et exécutez la commande suivante (adaptez les valeurs `-dname`, `-alias`, `-keystore`, `-storepass` et `-keypass` selon vos besoins) :

keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 \
        -keystore selfsigned.p12 -storetype PKCS12 -validity 365 \
        -dname "CN=localhost, OU=Developpement, O=MonEntreprise, L=MaVille, ST=MaRegion, C=FR" \
        -storepass MonMotDePasseSecret -keypass MonMotDePasseSecret

Explication des options :

  • `-genkeypair` : Génère une paire de clés (publique/privée).
  • `-alias tomcat` : Nom (alias) pour identifier cette entrée dans le keystore.
  • `-keyalg RSA` : Algorithme de la clé (RSA est courant).
  • `-keysize 2048` : Taille de la clé (2048 bits est un minimum raisonnable).
  • `-keystore selfsigned.p12` : Nom du fichier keystore à créer.
  • `-storetype PKCS12` : Format du keystore.
  • `-validity 365` : Durée de validité du certificat en jours.
  • `-dname "..."` : Informations du "Distinguished Name" pour le certificat. Pour le développement, `CN=localhost` est souvent utilisé pour correspondre à l'URL locale.
  • `-storepass MonMotDePasseSecret` : Mot de passe pour protéger le keystore.
  • `-keypass MonMotDePasseSecret` : Mot de passe pour protéger la clé privée (ici, identique au mot de passe du keystore).

Cette commande créera un fichier `selfsigned.p12`. Placez ce fichier dans votre projet (par exemple, `src/main/resources`) et configurez les propriétés `server.ssl.*` comme montré précédemment en utilisant le nom de fichier, l'alias (`tomcat`) et les mots de passe que vous avez définis. N'oubliez pas que votre navigateur affichera un avertissement de sécurité lors de l'accès à `https://localhost:8443` car le certificat n'est pas émis par une CA de confiance.

Utilisation de certificats de production (CA, Let's Encrypt)

En production, l'utilisation de certificats auto-signés est fortement déconseillée. Vous devez obtenir un certificat signé par une Autorité de Certification (CA) reconnue par les navigateurs et systèmes d'exploitation.

Plusieurs options s'offrent à vous :

  • CAs Commerciales : Des entreprises comme DigiCert, Sectigo, GlobalSign proposent différents types de certificats (validation de domaine, validation d'organisation, validation étendue) moyennant des frais annuels.
  • Let's Encrypt : Une CA gratuite, automatisée et ouverte, très populaire. Elle fournit des certificats de validation de domaine avec une durée de vie courte (90 jours), nécessitant une automatisation du renouvellement. Des outils comme Certbot simplifient grandement l'obtention et le renouvellement des certificats Let's Encrypt.

Le processus implique généralement de générer une demande de signature de certificat (CSR - Certificate Signing Request) à partir de votre serveur (ou via l'outil de la CA), de soumettre cette CSR à la CA, de prouver que vous contrôlez le domaine, puis de recevoir le certificat signé (souvent accompagné de certificats intermédiaires formant une chaîne de confiance).

Une fois que vous avez obtenu votre certificat et votre clé privée (et potentiellement les certificats intermédiaires), vous devez les importer dans un keystore (de préférence PKCS12) que Spring Boot pourra utiliser. Si votre CA vous fournit directement un fichier `.p12` ou `.pfx`, vous pouvez l'utiliser tel quel. Sinon, vous devrez peut-être utiliser `keytool` ou `openssl` pour combiner la clé privée, le certificat du serveur et les certificats intermédiaires dans un unique fichier keystore PKCS12.

# Exemple conceptuel avec openssl pour créer un PKCS12 à partir de fichiers séparés
# (les commandes exactes peuvent varier)
openssl pkcs12 -export -in votrecertificat.crt -inkey votrecleprivee.key \
             -certfile chaine_ca.crt -name monaliasdeprod \
             -out keystore_prod.p12

Configurez ensuite Spring Boot pour utiliser ce keystore de production comme décrit précédemment.

Redirection automatique de HTTP vers HTTPS

Une fois HTTPS configuré, il est généralement souhaitable de rediriger automatiquement toutes les requêtes arrivant sur le port HTTP (par défaut 80) vers le port HTTPS (par défaut 443). Cela garantit que les utilisateurs accèdent toujours à la version sécurisée de votre application.

Si vous utilisez Spring Security, c'est la méthode la plus simple. Vous pouvez configurer la redirection dans votre bean `SecurityFilterChain` :

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            // ... autres configurations de sécurité ...
            .requiresChannel(channel -> 
                channel.anyRequest().requiresSecure() // Exige HTTPS pour toutes les requêtes
            );
            // ... autres configurations ...
        return http.build();
    }
}

Cette configuration indique à Spring Security que toutes les requêtes doivent passer par un canal sécurisé (HTTPS). Si une requête arrive en HTTP, Spring Security initiera une redirection vers l'URL HTTPS correspondante.

Si vous n'utilisez pas Spring Security ou si vous avez besoin d'une configuration plus fine au niveau du conteneur web embarqué (Tomcat, Jetty, Undertow), vous pouvez utiliser un `WebServerFactoryCustomizer`. Voici un exemple pour Tomcat :

import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Value;

@Configuration
public class ServerConfig {

    @Value("${server.port.http:8080}") // Port HTTP à écouter
    private int httpPort;

    @Value("${server.port}") // Port HTTPS (doit être défini, ex: 8443 ou 443)
    private int httpsPort;

    @Bean
    public WebServerFactoryCustomizer servletContainerCustomizer() {
        return factory -> {
            // Configure le connecteur principal (HTTPS) sur le port défini dans server.port
            // (suppose que la configuration SSL est déjà faite via application.properties)

            // Ajoute un connecteur supplémentaire pour écouter sur le port HTTP
            Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
            connector.setScheme("http");
            connector.setPort(httpPort);
            connector.setSecure(false);
            connector.setRedirectPort(httpsPort); // Port vers lequel rediriger pour HTTPS
            factory.addAdditionalTomcatConnectors(connector);

            // Ajoute une contrainte de sécurité pour forcer HTTPS
            factory.addContextCustomizers((Context context) -> {
                SecurityConstraint securityConstraint = new SecurityConstraint();
                securityConstraint.setUserConstraint("CONFIDENTIAL"); // Exige un transport confidentiel (SSL)
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*"); // Appliquer à toutes les URL
                securityConstraint.addCollection(collection);
                context.addConstraint(securityConstraint);
            });
        };
    }
}

Cette approche configure Tomcat pour écouter sur les deux ports (HTTP et HTTPS) et rediriger automatiquement les requêtes HTTP vers HTTPS. Assurez-vous que les ports `server.port` (HTTPS) et `server.port.http` (HTTP, ici 8080 par défaut) sont correctement définis dans vos propriétés.

HTTPS derrière un Reverse Proxy ou un Load Balancer

Dans de nombreuses architectures de production, votre application Spring Boot ne sera pas directement exposée à Internet. Elle se trouvera derrière un reverse proxy (comme Nginx, Apache httpd) ou un load balancer (comme AWS ELB, HAProxy) qui gérera la terminaison SSL/TLS.

Dans ce scénario, le proxy/load balancer reçoit la requête HTTPS du client, la déchiffre, puis la transmet à votre application Spring Boot en HTTP simple sur le réseau interne. L'application Spring Boot doit cependant être consciente que la requête originale était en HTTPS pour générer correctement les URL absolues (par exemple, pour les redirections ou dans les liens générés) et pour que Spring Security applique correctement les règles `requiresSecure()`.

Le proxy/load balancer ajoute généralement des en-têtes à la requête transmise pour indiquer le protocole et le port d'origine, les plus courants étant :

  • `X-Forwarded-Proto` (valeur : `https`)
  • `X-Forwarded-Port` (valeur : `443`)
  • `X-Forwarded-For` (adresse IP du client original)

Spring Boot peut être configuré pour faire confiance à ces en-têtes et ajuster son comportement en conséquence. Ajoutez la propriété suivante à votre `application.properties` ou `yml` :

# application.properties
server.forward-headers-strategy=NATIVE
# ou FRAMEWORK si votre proxy utilise d'autres en-têtes standards
# application.yml
server:
  forward-headers-strategy: NATIVE # ou FRAMEWORK

Avec `NATIVE`, Spring Boot s'appuie sur la prise en charge native des en-têtes `X-Forwarded-*` par le conteneur web embarqué (Tomcat, Jetty, Undertow). `FRAMEWORK` utilise la propre logique de Spring pour interpréter ces en-têtes. `NATIVE` est souvent suffisant. Assurez-vous que votre reverse proxy/load balancer est correctement configuré pour ajouter ces en-têtes.