Spring Boot Configure Tomcat SSL over HTTPS

摘要: This tutorial demonstrates how to use spring boot to configure embedded tomcat SSL over HTTPS. You can optionally configure multiple Tomcat Connectors to support both HTTP and HTTPS at the same time. Or we also show how to redirect HTTP traffic to HTTPS automatically. These last two optional configuration cannot be used simultaneously.

This tutorial demonstrates how to use spring boot to configure embedded tomcat SSL over HTTPS. You can optionally configure multiple Tomcat Connectors to support both HTTP and HTTPS at the same time. Or we also show how to redirect HTTP traffic to HTTPS automatically. These last two optional configuration cannot be used simultaneously.

Project Structure

Let’s start by looking at the project structure.

Maven Dependencies

We use Apache Maven to manage our project dependencies. Make sure the following dependencies reside on the class-path.

<?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.memorynotfound.spring.boot.tomcat</groupId>
    <artifactId>ssl-https</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <url>http://memorynotfound.com</url>
    <name>Spring Boot - ${project.artifactId}</name>

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Generate Java Keystore and Self Signed Certificate

We are encrypting our network traffic, so we need a certificate to encrypt the traffic and a keystore to put the certificate in. Since we are developers, we can generate a self-signed-certificate to reduce costs while developing. By default java is shipped with a keytool which can generate self-signed-certificates and create a keystore. Use the following command:.

memorynotfound:ssl-https memorynotfound$ keytool -genkey \
-alias tomcat-localhost \
-keyalg RSA \
-keysize 2048 \
-validity 3650 \
-keystore keystore.jks

Enter keystore password:  
Re-enter new password: 
What is your first and last name?
  [Unknown]:  
What is the name of your organizational unit?
  [Unknown]:  
What is the name of your organization?
  [Unknown]:  
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=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
  [no]:  y

Enter key password for <tomcat-localhost>
        (RETURN if same as keystore password):  
Re-enter new password: 

Configure Tomcat using Spring Boot

We can configure Spring Boot using the application.yml file located in the src/main/resources folder.

server:
  port: 8443
  ssl:
    enabled: true
    key-alias: tomcat-localhost
    key-password: changeit
    key-store: classpath:keystore.jks
    key-store-provider: SUN
    key-store-type: JKS
    key-store-password: changeit

Redirect HTTP to HTTPS (1a: optional)

We can optionally configure the embedded tomcat to redirect HTTP traffic to HTTPS automatically.

package com.memorynotfound.spring.boot.tomcat;

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.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TomcatRedirectHttpToHttpsConfig {

    @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(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL);
        connector.setScheme("http");
        connector.setPort(8080);
        connector.setSecure(false);
        connector.setRedirectPort(8443);
        return connector;
    }
}

Support Both HTTP and HTTPS (1b: optional)

If you want to support both HTTP and HTTPS traffic, you’ll need to programatically create a second Tomcat Connector. We can configure the HTTPS connector using application.properties or application.yml files. Since the HTTP connector is the easiest to setup programatically. Note: these two optional configuration cannot be used simultaneously.

package com.memorynotfound.spring.boot.tomcat;

import org.apache.catalina.connector.Connector;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TomcatHttpAndHttpsConfig {

    @Bean
    public EmbeddedServletContainerFactory servletContainer(){
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
        tomcat.addAdditionalTomcatConnectors(httpConnector());
        return tomcat;
    }

    private Connector httpConnector(){
        Connector connector = new Connector(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL);
        connector.setScheme("http");
        connector.setPort(8080);
        connector.setSecure(false);
        return connector;
    }
}

Spring Boot

We use spring boot to bootstrap our application. The @SpringBootApplication triggers the EnableAutoConfiguration and ComponentScan. This is a convenience annotation that is equivalent to declaring @Configuration, @EnableAutoConfiguration and @Configuration.

package com.memorynotfound.spring.boot.tomcat;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

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

Simple Rest Controller

We create a simple rest service which is mapped to the root.

package com.memorynotfound.spring.boot.tomcat;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController {

    @GetMapping("/")
    public String welcome(){
        return "Hello, World";
    }
}

Console Output

When we start the application we can see that tomcat is initialized with ports 8843 and 8080.

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

...
s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8443 (https) 8080 (http)
...
s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8443 (https) 8080 (http)

Demo

In this demo we configured both HTTP and HTTPS connectors. When we go to the following URL: http://localhost:8080/ we receive the following output.

In the second example we configured that all traffic goes to HTTPS. If we go to http://localhost:8080/ we are automatically redirected to https://localhost:8443/. If we open the security tab in google chrome, we can inspect the certificate. Since we are using a self-signed certificate google chrome is telling us that the connection is not secure because the certificate isn’t validated against a known authority.

Download

上一篇: Spring Boot + Spring Security + Thymeleaf Form Login Example
下一篇: Spring Boot + Spring Mobile Serve Content Based on Device
 评论 ( What Do You Think )
名称
邮箱
网址
评论
验证
   
 

 


  • 微信公众号

  • 我的微信

站点声明:

1、一号门博客CMS,由Python, MySQL, Nginx, Wsgi 强力驱动

2、部分文章或者资源来源于互联网, 有时候很难判断是否侵权, 若有侵权, 请联系邮箱:summer@yihaomen.com, 同时欢迎大家注册用户,主动发布无版权争议的 文章/资源.

3、鄂ICP备14001754号-3, 鄂公网安备 42280202422812号