Main Tutorials

Spring Boot SSL (HTTPS) examples

In this tutorial, we will show you how to enable SSL (HTTPS) support for a Spring Boot web application (mvc + thymeleaf).

Tested with

  • Maven 3
  • Java 8
  • Spring Boot 2.2.4.RELEASE
  • Spring Boot default embedded Tomcat 9
  • Self-signed certificate (PKCS12)

To enable SSL or HTTPS for Spring Boot web application, puts the certificate file .p12 or .jks in the resources folder, and declares the server.ssl.* values in the application.properties

application.properties

# SSL
server.port=8443
server.ssl.key-store=classpath:cert.p12
server.ssl.key-store-password=123456

# JKS or PKCS12
server.ssl.keyStoreType=PKCS12

# Spring Security
# security.require-ssl=true

Done, starts the Spring Boot, and access https://localhost:8443

PEM file
The .pem is a popular certificate format for Apache and Nginx, but not supported in Java, here is an example to convert .pem into a .p12 format with OpenSSL.

1. Self-signed Certificate

For this example, we will use the JDK’s keytool to generate a self-sign certificate in PKCS12 format. The below command will create a PKCS12 cert, name mkyong.p12, puts this file into the resources folder.

Terminal

$ keytool -genkeypair -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore mkyong.p12 -validity 365

Enter keystore password:  
Re-enter new password:
What is your first and last name?
  [Unknown]:  yong
What is the name of your organizational unit?
  [Unknown]:  mkyong
What is the name of your organization?
  [Unknown]:  mkyong
What is the name of your City or Locality?
  [Unknown]:         
What is the name of your State or Province?
  [Unknown]:  
What is the two-letter country code for this unit?
  [Unknown]:  
Is CN=yong, OU=mkyong, O=mkyong, L=Unknown, ST=Unknown, C=Unknown correct?
  [no]:  yes

Note
More keytool usages

2. Project Directory

2.1 A standard Maven project structure.

project directory

3. Maven

3.1 Standard Spring Boot dependencies.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mkyong</groupId>
    <artifactId>spring-boot-ssl</artifactId>
    <version>1.0</version>

    <name>spring-boot-ssl</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- debugging -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <build>

        <finalName>spring-boot-web</finalName>

        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

4. Spring Boot

4.1 @SpringBootApplication to start and also a controller to return a page.

StartApplication.java

package com.mkyong;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@SpringBootApplication
@Controller
public class StartApplication {

    @GetMapping("/")
    public String index(final Model model) {
        model.addAttribute("title", "Spring Boot + SSL (HTTPS)");
        model.addAttribute("msg", "Welcome to the SSL!");
        return "index";
    }

    public static void main(String[] args) {
        SpringApplication.run(StartApplication.class, args);
    }

}

4.2 A thymeleaf page.

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"/>
    <link data-th-href="@{/css/main.css}" rel="stylesheet">
    <title>Spring Boot SSL Examples</title>
</head>
<body>

<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
    <a class="navbar-brand" href="#">Mkyong.com</div></a>
</nav>

<main role="main" class="container">
    <div class="starter-template">
        <h1 th:text="${title}">Default title.</h1>
        <p th:text="${msg}">Default text.</p>
    </div>
</main>

<script data-th-src="@{/js/main.js}"></script>
</body>

</html>

5. application.properties

application.properties

# SSL
server.port=8443
server.ssl.key-store=classpath:mkyong.p12
server.ssl.key-store-password=123456

# PKCS12 or JKS
server.ssl.keyStoreType=PKCS12

# Spring Security
# security.require-ssl=true

6. Run Spring Boot + SSL

Terminal

$ cd project
$ mvn clean package
$ java -jar target/spring-boot-web.jar

...
com.mkyong.StartApplication              : No active profile set, falling back to default profiles: default
o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8443 (https)
o.apache.catalina.core.StandardService   : Starting service [Tomcat]
org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.30]
o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 571 ms
o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8443 (https) with context path ''
com.mkyong.StartApplication              : Started StartApplication in 1.297 seconds (JVM running for 1.65)

Access https://localhost:8443

output 1

output 2

Due to the self-sign certificate, the browser will show a warning stated the certificate is invalid, ignore it, and clicks "advanced…continue" to continue.

Note
To solve the browser warning issue, get a free cert from Let’s Encrypt, or buy a cert from the trusted CA like Comodo or GeoTrust. Read more about SSL Certificate Authorities.

7. FAQs

Redirect all traffic from port 8080 to 8443.

StartApplication.java

package com.mkyong;

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.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class StartApplication {
    public static void main(String[] args) {
        SpringApplication.run(StartApplication.class, args);
    }

    // spring boot 2.x
    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
            @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;
    }

}

Download Source Code

$ git clone https://github.com/mkyong/spring-boot
$ cd spring-boot-ssl
$ mvn clean package
$ java -jar target/spring-boot-web.jar
access https://localhost:8443

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
11 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Pascal
4 years ago

Great tutorial. I’m wondering if this configuration will work when the springboot app is hosted on AWS?

Yigit Kemal Erinc
1 year ago
Reply to  Pascal

I believe it should work given that you open the port 8443, you can also configure a reverse proxy with NGINX to forward requests from 443 to port 8443 and enforce https 🙂

elgsylvain85
3 years ago

Hi MKYong,

Great tuto,
I’m facing the below exception after configured SSL.

Caused by: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty

Idea please?

OpenJDK11
Ubuntu 16

Regards,
Elgsylvain85

Elgsylvain85
3 years ago
Reply to  elgsylvain85

It seemed to me that the “OpenJDK” version did not correctly refer to the preinstalled Java certificates so my solution was to uninstall the “OpenJDK” version, download the Oracle version, unzip it then manually add all the references in the variables environments (JAVA_HOME …).

lay
1 year ago

Unable to start embedded Tomcat server when i try to generate own p12 file

Rodrigo Dias
1 year ago

Thank you very much! Very usefull.
Regards from Brazil.

alex
1 year ago

TY!!!

Ujjal Majumdar
2 years ago

Thank you for this.

RamaK
2 years ago

Hi MKYong, i would like to have the java source code to include .jks or .keystore in java code and send it to network as when i am adding .jks file to java/cacerts, i m getting No SSL client certificate present, ski pping SSL user authentication …at Network.

Thanks in Advance,
RK.

Jasintha peiris
2 years ago

Hi MKYong Sir,

Great tutorial……..👍 👍👍👍👍👍👍👍👍👍👍👍👍👍

#Spring Boot version “2.1.0.RELEASE” Keys->

server.ssl.key-alias=mkyong
server.ssl.key-store-type=JKS
server.ssl.key-password=mkyong
server.ssl.key-store=classpath:nameOfJks.jks

#Spring Boot version “2.4.5” Keys->

server.ssl.key-alias=mkyong
server.ssl.keyStoreType=JKS
server.ssl.key-store-password=mkyong
server.ssl.key-store=classpath:nameOfJks.jks

Thank you for the updates us and also much appreciated

bucenti.lb
3 years ago

Great tutorial, thanks