Spring Boot + SSL [https] Configuration + Securing REST API + Example

  • In today’s blog, we will learn – How we can enable HTTPS in the Spring Boot application? How we can redirect HTTP traffic to HTTPS protocol? How to create self-signed SSL Certificate for securing REST APIs.

High-Level Application Architecture

Here is the high-level application’s architecture with HTTPS-enabled functionality. In this working example, a rest API (/secured) has been exposed over HTTPS protocol. For enabling HTTPS in our application we need to generate a self-signed certificate that we can configure in our microservice/spring-boot application. Below we will learn in detail how to create & configure a self-signed certificate.

High Level Application Architecture

Technology Stack

Java 8
Maven 3.5.0
Spring Boot 2.2.4.RELEASE
Eclipse
Spring Boot Rest API

Spring Boot: Application Structure

Spring Boot: Application Structure

Spring Boot: Maven File (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>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.4.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>spring-boot-ssl-https-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-boot-ssl-https-server</name>
	<description>Demo project for Spring Boot Https</description>

	<properties>
		<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-web-services</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
		<resources>
			<resource>
				<directory>src/main/resources</directory>
			</resource>
		</resources>
	</build>

</project>

spring-boot: Application Configurations (application.properties)

# Application context name
server.servlet.contextPath=/springboothttpsserver

# SSL
server.port=8443
server.ssl.key-store=classpath:cert_thebasictechinfo.p12
server.ssl.key-store-password=root123


# JKS or PKCS12
server.ssl.keyStoreType=PKCS12

Spring Boot: @SpringBootApplication-SpringboothttpsApplication.java

This is the main class, here we are implementing ServletWebServerFactory bean and overriding postProcessContext method for redirecting HTTP request to HTTPS protocol.

package com.the.basic.tech.info.springboothttps;

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;
import org.springframework.context.annotation.Configuration;

@Configuration
@SpringBootApplication
public class SpringboothttpsApplication {

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

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

	// Custom Connector - redirecting http (8080) request to to https (8443)
	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;
	}

}

Spring Boot: @RestController (SecuredServerController.java)

Here in this RestController we have exposed/implemented Rest Interfaces for handling HTTPS requests from client. It will display a static message “Welcome to The Basic Tech Info !!! : <Current Date Time>”

package com.the.basic.tech.info.springboothttps.controller;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
class SecuredServerController {
	private static final Logger logger = LoggerFactory.getLogger(SecuredServerController.class);

	@RequestMapping("/secured")
	public String secured() {
		logger.info("Inside secured()");
		return "Welcome to The Basic Tech Info !!! : " + new Date();
	}

}

Create your own self signed SSL certificate

In this section, we will learn how to create your own self-signed SSL certificate. To get SSL digital certificate for our application we have two options

1. to create a self-signed certificate
2. to obtain SSL certificate from certification authority(CA) we call it CA certificate.

Command for generating self-signed SSL certificate

=== use below commands to generate keystore in your classpath ===

keytool -genkeypair -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore cert_thebasictechinfo.p12 -validity 365
command for generating self signed SSL certificate

Note: To view what is inside this keystore we can again use the keytool -list command

Application (microservice) Deploy, Run & Test

Run spring-boot-ssl-https-server: mvn spring-boot:run

D:\development\spring-boot-ssl-https-server>mvn spring-boot:run
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building spring-boot-ssl-https-server 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:2.2.4.RELEASE:run (default-cli) > test-compile @ spring-boot-ssl-https-server >>>
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ spring-boot-ssl-https-server ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ spring-boot-ssl-https-server ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to D:\development\spring-boot-ssl-https-server\target\classes
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ spring-boot-ssl-https-server ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\development\spring-boot-ssl-https-server\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ spring-boot-ssl-https-server ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\development\spring-boot-ssl-https-server\target\test-classes
[INFO]
[INFO] <<< spring-boot-maven-plugin:2.2.4.RELEASE:run (default-cli) < test-compile @ spring-boot-ssl-https-server <<<
[INFO]
[INFO]
[INFO] --- spring-boot-maven-plugin:2.2.4.RELEASE:run (default-cli) @ spring-boot-ssl-https-server ---
[INFO] Attaching agents: []

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.4.RELEASE)

2021-07-03 15:55:49.039  INFO 26056 --- [           main] c.t.b.t.i.s.SpringboothttpsApplication   : Starting SpringboothttpsApplication on LOCALHOST with PID 26056 (D:\development\spring-boot-ssl-https-server\target\classes started by 172025 in D:\development\spring-boot-ssl-https-server)
2021-07-03 15:55:49.043  INFO 26056 --- [           main] c.t.b.t.i.s.SpringboothttpsApplication   : No active profile set, falling back to default profiles: default
2021-07-03 15:55:49.937  INFO 26056 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.ws.config.annotation.DelegatingWsConfiguration' of type [org.springframework.ws.config.annotation.DelegatingWsConfiguration$$EnhancerBySpringCGLIB$$ce6262cb] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2021-07-03 15:55:50.038  INFO 26056 --- [           main] .w.s.a.s.AnnotationActionEndpointMapping : Supporting [WS-Addressing August 2004, WS-Addressing 1.0]
2021-07-03 15:55:51.370  INFO 26056 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8443 (https) 8080 (http)
2021-07-03 15:55:51.430  INFO 26056 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-07-03 15:55:51.432  INFO 26056 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.30]
2021-07-03 15:55:51.591  INFO 26056 --- [           main] o.a.c.c.C.[.[.[/springboothttpsserver]   : Initializing Spring embedded WebApplicationContext
2021-07-03 15:55:51.591  INFO 26056 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2467 ms
2021-07-03 15:55:51.811  INFO 26056 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-07-03 15:55:52.699  INFO 26056 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8443 (https) 8080 (http) with context path '/springboothttpsserver'
2021-07-03 15:55:52.705  INFO 26056 --- [           main] c.t.b.t.i.s.SpringboothttpsApplication   : Started SpringboothttpsApplication in 4.311 seconds (JVM running for 5.094)

Hit on the Browser: http://localhost:8080/springboothttpsserver/secured & it will be redirected to https://localhost:8443/springboothttpsserver/secured

Download Source Code (Attached)

Drop me your questions in the comments section if any.