If you're writing a Spring Boot application and want to and enable SSL (https) on the embedded Tomcat, here a few short steps you will need to take. (This has been tested with Spring Boot 2.0.5.RELEASE.)
- Get an SSL certificate.Fortunately, Java has a tool for doing this called
keytool
.keytool -genkey -alias tomcat \ -storetype PKCS12 -keyalg RSA -keysize 2048 \ -keystore keystore.p12 -validity 365
What does each flag mean? Let's break it down.-genkeypair
Generates a key pair (a public key and associated private key), wraps the public key into an X.509 v3 self-signed certificate, which is stored as a single-element certificate chain.-alias tomcat
This is how we will refer to the key pair in the keystore. Here we are going to call it 'tomcat'.-storetype PKCS12
This is the archive file format, used to bundle the private key with its certificate. Here we are using PKCS 12.-keyalg RSA
Specifies the algorithm to be used to generate the key pair. Here we are using RSA .-keysize 2048
The size (in bytes) of each key to be generated. Here we specify 2K.-keystore keystore.p12
. The name of the keystore file to generate. Here we are calling it 'keystore.p12'.-validity 365
How long the certificate is valid. Here we specify 1 year.
Since we did not use the-dname
flag,keytool
will interactively ask you questions for the certificate's distinguished name:Since this is for development, you may simply press 'Enter' at each prompt. (Be sure to answer 'yes' at the end though.) - Enable HTTPS in Spring BootThis part is pretty simple. Open your Spring Boot
application.properties
and configure it like this:server.port: 8443 server.ssl.key-store: keystore.p12 server.ssl.key-store-password: mypassword server.ssl.keyStoreType: PKCS12 server.ssl.keyAlias: tomcat
Restart your app and test the URL at https://localhost:8443. Since we self-signed our certificate, you will see an ugly warning like this:Depending on your browser, navigate to the 'Advanced' option and proceed to your application. - Redirect HTTP to HTTPSWouldn't it be nice if the old port redirected to this new secure port? Yes, it would.We will need to add a second Tomcat connector. However, we cannot do it in the
application.properties
So we'll have to do it programmatically, by creating our ownTomcatServletWebServerFactory
and overriding thepostProcessContext
method.Add this code to one of your@Configuration
beans (except forWebSecurityConfigurerAdapter
, if you're using one):@Bean public ServletWebServerFactory servletContainer() { TomcatServletWebServerFactory serverFactory = new TomcatServletWebServerFactory() { @Override protected void postProcessContext(Context context) { SecurityCollection collection = new SecurityCollection(); collection.addPattern("/*"); SecurityConstraint securityConstraint = new SecurityConstraint(); securityConstraint.setUserConstraint("CONFIDENTIAL"); securityConstraint.addCollection(collection); context.addConstraint(securityConstraint); } }; serverFactory.addAdditionalTomcatConnectors(redirectConnector()); return serverFactory; } private Connector redirectConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); connector.setPort(8080); connector.setSecure(false); connector.setRedirectPort(8443); return connector; }
Restart your app and test the URL at http://localhost:8080. Yay! It redirects to https.