SSL

Spring Boot 提供了配置 SSL 信任材料的能力,可应用于多种类型的连接,以支持安全通信。 以 spring.ssl.bundle 为前缀的配置属性可用于指定命名的信任材料集合及相关信息。

使用 Java KeyStore 文件配置 SSL

spring.ssl.bundle.jks 为前缀的配置属性可用于配置使用 Java keytool 工具创建并存储在 JKS 或 PKCS12 格式 Java KeyStore 文件中的信任材料集合。 每个集合都有一个用户自定义的名称,可用于引用该集合。

用于保护嵌入式 Web 服务器时,通常会配置一个包含证书和私钥的 Java KeyStore,如下例所示:

  • Properties

  • YAML

spring.ssl.bundle.jks.mybundle.key.alias=application
spring.ssl.bundle.jks.mybundle.keystore.location=classpath:application.p12
spring.ssl.bundle.jks.mybundle.keystore.password=secret
spring.ssl.bundle.jks.mybundle.keystore.type=PKCS12
spring:
  ssl:
    bundle:
      jks:
        mybundle:
          key:
            alias: "application"
          keystore:
            location: "classpath:application.p12"
            password: "secret"
            type: "PKCS12"

用于保护客户端连接时,通常会配置一个包含服务器证书的 Java KeyStore 作为 truststore,如下例所示:

  • Properties

  • YAML

spring.ssl.bundle.jks.mybundle.truststore.location=classpath:server.p12
spring.ssl.bundle.jks.mybundle.truststore.password=secret
spring:
  ssl:
    bundle:
      jks:
        mybundle:
          truststore:
            location: "classpath:server.p12"
            password: "secret"

除了文件位置外,也可以提供其 Base64 编码内容。 如果选择此选项,属性值应以 base64: 开头。

详见 JksSslBundleProperties 支持的全部属性。

注意:如果你使用环境变量配置集合,集合名称会被 始终转换为小写

使用 PEM 编码证书配置 SSL

spring.ssl.bundle.pem 为前缀的配置属性可用于配置 PEM 编码文本形式的信任材料集合。 每个集合都有一个用户自定义的名称,可用于引用该集合。

用于保护嵌入式 Web 服务器时,通常会配置一个包含证书和私钥的 keystore,如下例所示:

  • Properties

  • YAML

spring.ssl.bundle.pem.mybundle.keystore.certificate=classpath:application.crt
spring.ssl.bundle.pem.mybundle.keystore.private-key=classpath:application.key
spring:
  ssl:
    bundle:
      pem:
        mybundle:
          keystore:
            certificate: "classpath:application.crt"
            private-key: "classpath:application.key"

用于保护客户端连接时,通常会配置一个包含服务器证书的 truststore,如下例所示:

  • Properties

  • YAML

spring.ssl.bundle.pem.mybundle.truststore.certificate=classpath:server.crt
spring:
  ssl:
    bundle:
      pem:
        mybundle:
          truststore:
            certificate: "classpath:server.crt"

除了文件位置外,也可以提供其 Base64 编码内容。 如果选择此选项,属性值应以 base64: 开头。

PEM 内容也可直接用于 certificateprivate-key 属性。 如果属性值包含 BEGINEND 标记,则会被视为 PEM 内容而不是资源位置。

以下示例展示了如何定义 truststore 证书:

  • Properties

  • YAML

spring.ssl.bundle.pem.mybundle.truststore.certificate=\
-----BEGIN CERTIFICATE-----\n\
MIID1zCCAr+gAwIBAgIUNM5QQv8IzVQsgSmmdPQNaqyzWs4wDQYJKoZIhvcNAQEL\n\
BQAwezELMAkGA1UEBhMCWFgxEjAQBgNVBAgMCVN0YXRlTmFtZTERMA8GA1UEBwwI\n\
...\n\
V0IJjcmYjEZbTvpjFKznvaFiOUv+8L7jHQ1/Yf+9c3C8gSjdUfv88m17pqYXd+Ds\n\
HEmfmNNjht130UyjNCITmLVXyy5p35vWmdf95U3uEbJSnNVtXH8qRmN9oK9mUpDb\n\
ngX6JBJI7fw7tXoqWSLHNiBODM88fUlQSho8\n\
-----END CERTIFICATE-----\n
spring:
  ssl:
    bundle:
      pem:
        mybundle:
          truststore:
            certificate: |
              -----BEGIN CERTIFICATE-----
              MIID1zCCAr+gAwIBAgIUNM5QQv8IzVQsgSmmdPQNaqyzWs4wDQYJKoZIhvcNAQEL
              BQAwezELMAkGA1UEBhMCWFgxEjAQBgNVBAgMCVN0YXRlTmFtZTERMA8GA1UEBwwI
              ...
              V0IJjcmYjEZbTvpjFKznvaFiOUv+8L7jHQ1/Yf+9c3C8gSjdUfv88m17pqYXd+Ds
              HEmfmNNjht130UyjNCITmLVXyy5p35vWmdf95U3uEbJSnNVtXH8qRmN9oK9mUpDb
              ngX6JBJI7fw7tXoqWSLHNiBODM88fUlQSho8
              -----END CERTIFICATE-----

详见 PemSslBundleProperties 支持的全部属性。

注意:如果你使用环境变量配置集合,集合名称会被 始终转换为小写

应用 SSL 集合

通过属性配置后,可以在 Spring Boot 自动配置的多种连接类型的配置属性中通过名称引用 SSL 集合。 更多信息请参见 嵌入式 Web 服务器数据技术REST 客户端 相关章节。

使用 SSL 集合

Spring Boot 会自动配置一个类型为 SslBundles 的 bean,用于访问通过 spring.ssl.bundle 属性配置的每个命名集合。

可以从自动配置的 SslBundles bean 获取 SslBundle,并用于创建配置客户端库 SSL 连接的对象。 SslBundle 提供了分层方式获取这些 SSL 对象:

此外,SslBundle 还提供了关于所用密钥、协议及应应用于 SSL 引擎的选项的详细信息。

以下示例展示了如何获取 SslBundle 并用其创建 SSLContext

  • Java

  • Kotlin

import javax.net.ssl.SSLContext;

import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.stereotype.Component;

@Component
public class MyComponent {

	public MyComponent(SslBundles sslBundles) {
		SslBundle sslBundle = sslBundles.getBundle("mybundle");
		SSLContext sslContext = sslBundle.createSslContext();
		// do something with the created sslContext
	}

}
import org.springframework.boot.ssl.SslBundles
import org.springframework.stereotype.Component

@Component
class MyComponent(sslBundles: SslBundles) {

    init {
        val sslBundle = sslBundles.getBundle("mybundle")
        val sslContext = sslBundle.createSslContext()
        // do something with the created sslContext
    }

}

重新加载 SSL 集合

当密钥材料发生变化时,SSL 集合可以被重新加载。 消费该集合的组件必须兼容可重载的 SSL 集合。 目前以下组件是兼容的:

  • Tomcat Web 服务器

  • Netty Web 服务器

要启用重新加载,需要通过配置属性进行设置,如下例所示:

  • Properties

  • YAML

spring.ssl.bundle.pem.mybundle.reload-on-update=true
spring.ssl.bundle.pem.mybundle.keystore.certificate=file:/some/directory/application.crt
spring.ssl.bundle.pem.mybundle.keystore.private-key=file:/some/directory/application.key
spring:
  ssl:
    bundle:
      pem:
        mybundle:
          reload-on-update: true
          keystore:
            certificate: "file:/some/directory/application.crt"
            private-key: "file:/some/directory/application.key"

此时会有文件监视器监控这些文件,如果发生变化,SSL 集合会被重新加载。 这会进一步触发消费组件的重新加载,例如 Tomcat 会在启用 SSL 的连接器中轮换证书。

你可以通过 spring.ssl.bundle.watch.file.quiet-period 属性配置文件监视器的静默期(以确保没有更多变更)。