Using Spring Boot with SSL

In this tutorial we will learn how to configure Spring Boot embedded server to accept HTTPS request for your Web applications. by creating a self signed certificate.

In order to create a self-signed certificate, we can use the keytool toolkit which is included in the JDK. Let’s create a server certificate as follows:

$ keytool -genkey -alias myalias -keyalg RSA -keysize 2048 -validity 700 -keypass secret -storepass secret -keystore server.jks

Let’s understand above command –

  • -genkey – is the keytool command to generate the public/private key.
  • -alias – indicates the alias of the certificate, which is used by SSL/TLS layer
  • -keyalg RSA -keysize 2048 -validity 700 – are indicating the crypto algorithm, keysize and certificate validity.
  • -keypass secret -storepass secret  – are the passwords of our truststore and keystore
  • -keystore server.jks – is the actual keystore where the certificate and public/private key will be stored. Here we are using JKS fromat – Java Key Store, there are other formats as well for keystore.

We will copy the generated server.jks in the resources folder of our Web application so that’s available to the application’s classpath:

$ cp server.jks src/main/resources/

After that, within the application.properties configuration file, we will set the keystore attributes and the port used by the Web server:

server.port=8443
server.ssl.key-alias=myalias
server.ssl.key-store-password=secret
server.ssl.key-store=classpath:server.jks
server.ssl.key-store-provider=SUN
server.ssl.key-store-type=JKS

As an example, we will add the following Controller class, which returns a message:

@RestController
public class DemoController
{


    @RequestMapping("/secure")
    public String echo()
    {
        return "Hello from Spring Boot SSL";
    }


}

After that, run the application:

$ mvn install spring-boot:run

As you can see from the following curl command, a TLS handlshake is performed when a request to https://localhost:8443/secure lands on the Web server:

$ curl --insecure -v https://localhost:8443/secure

*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, [no content] (0):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: C=Unknown; ST=Unknown; L=Unknown; O=Unknown; OU=Unknown; CN=Frank Marchioni
*  start date: Jul 16 10:37:01 2021 GMT
*  expire date: Jun 16 10:37:01 2023 GMT
*  issuer: C=Unknown; ST=Unknown; L=Unknown; O=Unknown; OU=Unknown; CN=Frank Marchioni
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
* TLSv1.3 (OUT), TLS app data, [no content] (0):
> GET /secure HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/7.61.1
> Accept: */*

Redirecting HTTP requests to HTTPS

If your application exposes the default HTTP port as well, you might want to redirect incoming HTTP requests to HTTPS. To do that, you need to override the postProcessContext method of the Embedded Tomcat Server:

@Bean
public EmbeddedServletContainerFactory servletContainer() {
  TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
      @Override
      protected void postProcessContext(Context context) {
        SecurityConstraint securityConstraint = new SecurityConstraint();
        securityConstraint.setUserConstraint("CONFIDENTIAL");
        SecurityCollection collection = new SecurityCollection();
        collection.addPattern("/*");
        securityConstraint.addCollection(collection);
        context.addConstraint(securityConstraint);
      }
    };
   
  tomcat.addAdditionalTomcatConnectors(redirectConnector());
  return tomcat;
}


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;
}

Source code for this tutorial: https://github.com/fmarchioni/masterspringboot/tree/master/security/demo-ssl

Exit mobile version