【问题标题】:Spring Boot - Enable SSL (HTTPS) with CA certificateSpring Boot - 使用 CA 证书启用 SSL (HTTPS)
【发布时间】:2017-07-13 09:35:59
【问题描述】:

也许我会在这里寻求帮助。我想在 Spring Boot 应用程序上启用 SSL。我有这样的配置:

服务器:端口:8999 ssl: 启用:真 密钥库:类路径:keystore.jks 密钥库密码:mypass 密钥密码:mypass

问题是我的密钥库。我已使用别名“tomcat”将 *crt 文件导入密钥库:

keytool -importcert -file certificate.crt -keystore native.jks -alias tomcat

但是,我仍然无法正确访问我的 rest api。它在Firefox中呕吐并出现错误:

SSL_ERROR_RX_RECORD_TOO_LONG

  • 它不起作用。如何制作正确的密钥库以使其正常工作?我使用 CA 证书颁发,而不是自签名。我有类似的文件:

certificate.crt、certificate.p12、certificate.pk、privkey.pem 和 三个文件 root_ca_1.ca-bundle、root_ca_2.ca-bundle、 root_ca_3.ca-bundle

。那是我的全部了。我对 ssl 主题非常陌生,只是阅读了一些教程并尝试了一些 keytool 命令来使其工作。我会很感激帮助。提前谢谢你。

【问题讨论】:

标签: java ssl spring-boot https jks


【解决方案1】:

我花了一个下午才弄清楚这个确切的问题,所以我将在这里分享我的过程。

以下每个参考资料都提供了有关如何生成和使用自签名证书的说明。这并不是我想要做的,但这些都包含一些有用的背景信息。

参考:

我已经为 *.jimtough.org 'wildcard' 域购买了真正的 CA 颁发的 SSL 证书。我从http://www.namecheap.com/ 购买了证书,但实际的证书颁发机构 (CA) 是 Comodo。

作为 CA 购买/激活程序的一部分,我需要遵循以下说明:

请注意,我之所以选择遵循他们的 AWS 说明,是因为我是 AWS 用户,并且拥有一个随时可用的 EC2 服务器,并且服务器上已经安装了 OpenSSL 和 Java。有许多其他替代方法可以执行相同的过程,因此请进一步搜索以找到适合您的“生成 CSR”说明。

在这一步结束时,我有以下两个文件:

  • csr.pem - 这用作 SSL 证书请求/激活过程的一部分
  • private.key - 这是我的 SSL 证书的私钥部分,稍后我需要在我的服务器上安装证书。 保密。请妥善保管。

在我完成 SSL 证书的购买和验证程序后,CA 向我发回了一个 .zip 文件,其中包含一个 .p7b、.crt 和 .ca-bundle 文件。

以下参考链接之一解释了这些证书文件类型之间的区别:

  • .p7b - 此类型应与基于 Java 的应用程序兼容(PKCS#7 格式)
  • .crt - 这种类型应该与大多数其他东西兼容 - 上面的链接表明这是 PEM 格式
  • .ca-bundle - 不确定何时使用 - 上面的链接表明这是 PEM 格式

参考:

接下来,我需要弄清楚如何使用上面列出的文件来为我的 Spring Boot 应用程序配置 HTTPS。

我将按照以下教程的相关部分来获得我需要的东西:

注意:在这两个教程中,我不会按照他们关于创建自签名证书的部分进行操作,因为我已经拥有由真实 CA 颁发的真实证书。

他们的说明中的第一个相关步骤是创建一个新的 Java 密钥库。要求是:

  • 必须安装 Java,所以我可以访问“keytool”实用程序
  • 必须安装“openssl”实用程序,这样我才能使用我的 .key 和 .p7b 文件作为输入创建一个 .p12 文件

我将使用我的 AWS EC2 Linux 服务器来执行此操作。我的服务器已经安装了 Java/keytool 和 OpenSSL 实用程序。 首先,我需要使用 OpenSSL 实用程序创建一个 .p12 文件(如果我理解正确的话)将包含我的 私钥和 CA 颁发的证书。其次,我需要创建一个新的 Java 密钥库,其中包含一个导入的 .p12 文件的副本。

  • openssl pkcs12 -export -out jimtough-dot-org.p12 -name "jimtough-dot-org" -inkey private.key -in __jimtough_org.crt
    • 重要提示:需要在“导出密码”提示处提供密码,否则下一步keytool导入会失败
  • keytool -importkeystore -srckeystore jimtough-dot-org.p12 -srcstoretype PKCS12 -destkeystore jimtough-dot-org-keystore.jks -deststoretype JKS
    • 您需要提供在“openssl”命令中使用的密码
    • 您还需要为正在创建的密钥库提供新密码
  • (可选)keytool -importkeystore -srckeystore jimtough-dot-org-keystore.jks -destkeystore jimtough-dot-org-keystore.pkcs12 -deststoretype pkcs12
    • 我收到了来自“keytool”的关于 JKS 是一种专有格式的警告,并建议我将我的密钥库转换为 PKCS12 格式,所以我使用这个可选命令这样做了

最后,我需要将我新创建的 Java 密钥库与我的 Spring Boot 应用程序打包并配置应用程序以使用它。

参考:

我参考了上面的两个 Baeldung 教程,并且能够获得使我的 Spring Boot(启用 Spring Security)工作所需的详细信息。

我在现有的 'src/main/resources' 下创建了一个新的 'keystore' 文件夹,并将我新创建的两个密钥库文件都复制到那里(我保留了这两种格式)。

我将下面的块添加到我的 Spring Boot 应用程序的 application.properties 文件中。

#--------------------------------------------------------------------------------------------------
# SSL CONFIGURATION
# The format used for the keystore. It could be set to JKS in case it is a JKS file
#server.ssl.key-store-type=JKS
server.ssl.key-store-type=PKCS12
# The path to the keystore containing the certificate
#server.ssl.key-store=classpath:keystore/jimtough-dot-org-keystore.jks
server.ssl.key-store=classpath:keystore/jimtough-dot-org-keystore.pkcs12
server.ssl.key-store-password=mykeystorepassword
server.ssl.key-alias=jimtough-dot-org
server.ssl.enabled=true
server.port=8443
#--------------------------------------------------------------------------------------------------

正如预期的那样,当我尝试使用 https://localhost:8443/ 作为 URL 连接到本地运行的 Spring Boot 应用程序实例时,我从浏览器中收到了一堆警告。发生这种情况是因为浏览器正确识别了“localhost”与创建我的 SSL 证书以在其上运行的预期“jimtough.org”域之间的不匹配。当我将应用程序部署到主机名为“anything.jimtough.org”(或只是www.jimtough.org)的服务器时,不应出现任何警告。

就是这样! HTTPS 快乐!

【讨论】:

  • 这非常好,我需要的一切,因为我已经购买了证书。我发现的所有其他东西都是针对自签名证书的,这对于生产来说是不现实的。只是想补充一下,这些是我最终遵循的步骤并跳过了最初的步骤:1)我已经从我的 ssl 提供商那里获得了一个 .pfx 文件,所以我下载了私钥和 .pfx 文件 2)我了解到一个 .pfx 文件。 pfx 文件也是一个 .p12 文件,您可以根据需要重命名。我没有这样做,只是使用了 .pfx 文件并生成了我的密钥库。 3)然后我使用密钥库生成 pkcs12 文件
  • 你拯救了我的一天!谢谢很好的一步一步的解释。我正在使用为前端和后端安装 Godday ssl 的步骤。它的作用就像魅力
【解决方案2】:

好吧,您需要在 ssl 配置中添加更多属性

server:
ssl:
  key-store: classpath:config/tls/keystore.p12
  key-store-password: password ##this will be your certificate password
  key-store-type: PKCS12
  ciphers: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
  enabled-protocols: TLSv1.2
http2:
  enabled: true

确保 p12 密钥库文件存在于 config/tls 中的类路径 (src/main/resources) 下

但是要生成密钥库文件,请使用下面的 openssl 命令 将使用 .crt 和 .key 文件生成 .p12 文件。

.crt 和 .key 存在于文件夹 CA 下,文件 p12 文件将是 CA下生成

请注意,之后您将要求输入证书密码 运行以下命令

openssl pkcs12 -export -in CA/certificate.crt -inkey CA/certificate.key -name certificate -out CA/certificate.p12

如果您想将此证书添加到本地 cacert,请使用 下面的命令

在 jre\lib\security 下

keytool -importcert -noprompt -trustcacerts  -alias ca.certificate  -file   CA/certificate.crt -keystore   cacerts -storepass changeit

【讨论】:

    【解决方案3】:

    不要将 spring-boot 用于 SSL 连接。让反向代理处理 SSL 终止。
    因此,有可能一个工具可以自动更新您的证书(如 certbot)。
    而且您不需要将(秘密)私钥放入您的应用程序。

    共享您的应用程序更简单。服务器管理员只需要设置反向代理(或者在 kubernetes 等云系统中已经有一些熟悉的东西)并且可以扩展您的应用程序。

    好处

    • 可扩展的应用程序
    • 更简单的弹簧设置
    • 您的应用程序中没有秘密
    • 应用程序使用更简单 (#cloudSystems)
    • 大多数反向代理都与 certbot 兼容

    【讨论】:

    • 尽管投了反对票,但这实际上是一个很好的建议。虽然它没有回答问题,但有时最好在问题之外看看。如果使用反向代理,则完全摆脱了创建密钥库和添加证书等业务。而且很可能会遇到 certbot 颁发的证书,这意味着证书需要经常更新。这一切都非常适合基于 apache/nginx 的反向代理,并且可以轻松自动化并轻松支持。当应用程序扩展需要负载平衡和内容加速时,无论如何你最终都会落后于 RP。