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.
Java 8
Maven 3.5.0
Spring Boot 2.2.4.RELEASE
Eclipse
Spring Boot Rest API
<?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>
# 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
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;
}
}
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();
}
}
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.
=== use below commands to generate keystore in your classpath ===
keytool -genkeypair -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore cert_thebasictechinfo.p12 -validity 365
Note: To view what is inside this keystore we can again use the keytool -list command
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)
Drop me your questions in the comments section if any.