in certificat ssl https spring boot tomcat ~ temps de lecture.

Configuration SSL de Tomcat dans Spring Boot

Vous souhaitez faire en sorte que votre Tomcat embarqué à votre application Spring Boot puisse être configuré avec un certificat SSL, signé par vos soins ou par une autorité de certification ?
Il vous faut tout d'abord clarifier votre besoin :

  • certaines de vos pages doivent être accessibles en non-sécurisées et d'autres en sécurisées (au sens HTTPS)
  • toutes vos pages doivent être sécurisées (au sens HTTPS)

Apache Tomcat SSL

Accès HTTP et HTTPS

Ce premier cas est le plus complexe, car il faut :

  • programmatiquement configurer votre Tomcat embarqué afin de rendre accessibles un port HTTP et un port HTTPS à la fois
  • configurer correctement la partie SSL du connecteur Tomcat

Pour le premier point voici un exemple de paramétrage au niveau de vos properties :

server.port=9090

api.tomcat.ssl.enabled=true  
api.tomcat.ssl.port=9091  
api.tomcat.ssl.key-store=classpath:ssl/keystore.jks  
api.tomcat.ssl.key-store-password=changeit  
api.tomcat.ssl.key-store-type=JKS  

Ssl class mapping to Java via @EnableConfigurationProperties :

public static class Ssl {

    private boolean enabled;
    private int port;
    private Resource keyStore;
    private String keyStorePassword;
    private String keyStoreType;

    /** getters & setters */
    ...
}

On note bien la présence de deux ports, 9090 pour la partie HTTP et 9091 pour la partie HTTPS.
Les valeurs des propriétés key-store, key-store-password et key-store-type sont liées à la génération de votre certificat SSL, dans l'exemple ci-dessus celui-ci est auto-signé et a été généré avec l'outil keytool du JDK (format .jks par défaut mais .p12 fonctionne tout autant).

Jusqu'ici, seul l'accès en HTTP sur le port 9090 fonctionne, à présent il faut configurer Tomcat afin d'exploiter les propriétés concernant le SSL, voici un exemple de configuration Java Spring :

@Configuration
public class TomcatConnectorsConfiguration {

    @Autowired
    private ApiProperties apiProperties;

    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();

        if (apiProperties.getTomcat().getSsl().isEnabled()) {
            tomcat.addAdditionalTomcatConnectors(createConnectorSSL());
        }
        return tomcat;
    }

    /**
     * Configuration connecteur SSL
     */
    private Connector createConnectorSSL() {
        Connector connector = new Connector("HTTP/1.1");
        Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
        try {
            File keystore = apiProperties.getTomcat().getSsl().getKeyStore().getFile();
            connector.setScheme("https");
            connector.setSecure(true);
            connector.setPort(apiProperties.getTomcat().getSsl().getPort());
            protocol.setSSLEnabled(true);
            protocol.setKeystoreFile(keystore.getAbsolutePath());
            protocol.setKeystorePass(apiProperties.getTomcat().getSsl().getKeyStorePassword());
            protocol.setKeystoreType(apiProperties.getTomcat().getSsl().getKeyStoreType());
            return connector;

        } catch (IOException ex) {
            throw new IllegalStateException("cant access keystore: [" + "keystore" + "]", ex);
        }
    }

}

Ce nouveau connecteur SSL greffé au Tomcat embarqué est suffisant pour que les pages de votre application Web soient aussi accessibles en HTTPS sur le port 9091. Le tour est joué.

Accès HTTPS uniquement

Ce cas est plus simple car il suffit de définir les properties "natives" de Spring Boot et tout fonctionne magiquement, les voici en reprenant les mêmes valeurs que dans l'exemple précédent :

server.port=9091

server.ssl.enabled=true  
server.ssl.key-store=classpath:ssl/keystore.jks  
server.ssl.key-store-password=changeit  
server.ssl.key-store-type=JKS  

C'est tout, toutes vos pages sont maintenant accessibles uniquement en HTTPS via le port 9091.
Merci Spring !

comments powered by Disqus