前言

本文主要介绍Spring Boot HTTPS相关配置,基于自签证书实现;

通过本例子,同样可以了解创建SSL数字证书的过程;

本文概述

Spring boot HTTPS 配置

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

Http请求自动跳转到Https

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

更多详细配置,请继续阅读

相关术语

在继续学习之前,先了解下相关术语:

SSL:SSL(Secure Sockets Layer 安全套接层),用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络上之传输过程中不会被截取及窃听。

TLS:安全传输层协议(TLS)用于在两个通信应用程序之间提供保密性和数据完整性。该协议由两层组成: TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)。

HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
truststore
Truststore and Keystore:主要用于Java中存储证书,它们之间的区别是truststore用于存储public证书,而keystore用于存储private证书

创建自签证书

可以通过以下两种方式获取SSL数字证书

  1. 创建自签证书
  2. 从CA机构获取

出于方便本例子将使用自签证书,通过java keytool命令生成,如下示例:

keytool -genkey -alias selfsigned_localhost_sslserver -keyalg RSA -keysize 2048 -validity 700 -keypass changeit -storepass changeit -keystore ssl-server.jks

简单解释下以上命令的含义:
-genkey – keytool命令,用于生成证书,事实上keytool是一个多用途和健壮的工具,支持丰富的命令参数;
-alias selfsigned_localhost_sslserver 声明证书的别名,SSL/TLS层使用;
-keyalg RSA -keysize 2048 -validity 700 –设置加密算法、秘钥大小、validity参数.
-keypass changeit -storepass changeit– truststore 和 keystore的密码;
-keystore ssl-server.jks – 存储证书、公钥私钥的文件,使用JKS格式 – Java Key Store,除了JKS外,还有其它格式可选择;

一旦我们执行以上命令,会要求我们输入证书相关信息,最终效果如下:

springboot配置ssl证书crt和key springboot ssl配置_java

最终生成的证书在我们执行keytool命令的目录下,如果要查看证书内部是什么,可以使用keytool -list命令:

keytool -list -keystore ssl-server.jks

创建Spring Boot工程配置SSL

生成Spring Boot工程

生成Spring Boot最简便的方式是通过SPRING INITIALIZR网站来创建,我们选择Web和Rest依赖,并输入Maven GAV 坐标,然后选择下载,下载骨架工程,解压并导入到我们的IDE中即可;

springboot配置ssl证书crt和key springboot ssl配置_HTTP_02

添加RestController

出于测试考虑,我们将创建一个非常简单的RestController,代码如下:

@RestController
class SecuredServerController{
    
    @RequestMapping("/secured")
    public String secured(){
        System.out.println("Inside secured()");
        return "Hello user !!! : " + new Date();
    }
}

Spring boot SSL配置

首先我们需要拷贝ssl-server.jks文件到我们的resources 目录下,然后打开application.properties文件,添加如下配置:

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

配置完成,就这么简单,是不是很方便;

Demo演示

完成以上步骤后:
我们就可以通过mvn clean install命令构建工程,
通过java -jar target\ssl-server-0.0.1-SNAPSHOT.jar命令启动应用,端口为8443 ,
最后通过 https://localhost:8443/secured URL访问我们的资源;

由于我们的REST服务是GET方法,我们可以通过浏览器进行测试,访问https://localhost:8443/secured URL即可;

由于我们的证书不是受信任的颁发机构颁发的,所以我们需要添加例外,之后就可以访问了,如下图所示:

springboot配置ssl证书crt和key springboot ssl配置_HTTP_03

HTTP 请求跳转到HTTPS

这是一个可选的步骤,有时候我们希望全站都是安全的,就需要所有http请求都能自动跳转到https;

假设我们的HTTP端口是8080,HTTPS端口是8443,希望所有的8080端口请求都能自动跳转到8443 ,实现该功能只需要作如下配置即可:

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

最后,做个测试,访问HTTP接口 http://localhost:8080/secured ,浏览器上观察是否自动跳转到HTTPS URL了,不出意外,应该是OK的