Tomcat、Spring Boot 的证书还在手动换?教你自动续期和部署

简介: Java 应用换证书比 Nginx 多两步:转成 keystore,再重启应用。证书有效期缩短到 100 天、47 天以后,这两步也得自动化。别名、密码、重启检查有一处没处理好,应用就会在续期后第一次重启时起不来。

Java 应用换证书比 Nginx 多两步。Nginx 拿到 PEM 文件,reload 一下就生效;Tomcat 和 Spring Boot 通常读的是 keystore(.jks 或 .p12),每次续期都要从云厂商控制台下载 Tomcat 格式的证书,或者自己用 openssl pkcs12、keytool 把证书和私钥转成 keystore,替换文件,再重启应用。证书一年换一次时,这些步骤手动做没什么问题。现在新签发的公开证书最长只有 200 天,2027 年 3 月 15 日起降到 100 天,2029 年 3 月 15 日起降到 47 天,到那时差不多每个月都要换一次。

这篇讲 Java 应用的证书怎么做成自动续期和部署:先确认证书由谁加载,再分别说 Tomcat 和 Spring Boot 的配置,然后是换证时最常见的三个错误,最后是两种自动化做法:自己写 Certbot hook,或者交给 LapseZero 托管。

先确认证书配在 Nginx 还是 Java 应用上

很多 Java 项目前面有 Nginx 或负载均衡,由它们处理 HTTPS,Tomcat 只监听 8080。这种情况下证书和 Java 没有关系,按 Nginx 或云产品的方式续期就行,keystore 那一套用不上。

判断方法很直接:Tomcat 看 conf/server.xml 里有没有带 SSLHostConfig 的 Connector,Spring Boot 看 application.yml、application.properties 和启动参数里有没有 server.ssl。都没有,一般就是 Java 应用不加载证书。下面的内容只针对 Java 自己加载证书的情况。

Tomcat 的证书配置

Tomcat 8.5 以后(包括 9、10、11)的写法相同,都是在 Connector 里放一个 SSLHostConfig:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true">
  <SSLHostConfig>
    <Certificate certificateKeystoreFile="/opt/tomcat/ssl/tomcat.p12"
                 certificateKeystorePassword="changeit"
                 certificateKeystoreType="PKCS12" />
  </SSLHostConfig>
</Connector>

自动化只关心 Certificate 上的几个属性:

  • certificateKeystoreFile:keystore 文件路径,续期后的新文件就写到这里。
  • certificateKeystorePassword:keystore 密码,新文件必须用同一个密码生成。
  • certificateKeystoreType:不写时默认是 JKS。现在建议用 PKCS12,并显式写出来。
  • certificateKeyAlias:示例里没写。不写时 Tomcat 用 keystore 里读到的第一个密钥,keystore 里只有一张证书时这样最省事。

如果不想转 keystore,Tomcat 8.5 起也能直接读 PEM 文件,用 certificateFile、certificateKeyFile、certificateChainFile 三个属性分别指向证书、私钥和中间证书。已经在用 keystore 的不必为了自动化改成 PEM,两种都能自动部署。

文件换好以后要让 Tomcat 重新加载。最简单的是重启,代价是重启期间 HTTPS 不可用:一台小内存测试机上,Tomcat 10.1 正常重启时 HTTPS 中断了大约 7 秒。不想中断可以用 Manager 应用的 sslReload,它只重新读取证书和私钥文件,不重新解析 server.xml:

curl -fsS -u deployer:password "http://localhost:8080/manager/text/sslReload" | grep -q '^OK'

用这个命令要先启用 Manager 应用,并给账号分配 manager-script 角色。Manager 执行失败时返回的是以 FAIL 开头的文本,curl 本身仍然成功,所以要用 grep 检查结果,失败时命令才会返回非 0。

Spring Boot 的证书配置

Spring Boot 内嵌 Tomcat,证书写在应用配置里:

server:
  port: 8443
  ssl:
    key-store: file:/opt/app/ssl/app.p12
    key-store-type: PKCS12
    key-store-password: changeit

Spring Boot 2.7 和 3.x 都是这个写法。这里最需要注意的是 file:。很多教程写的是 classpath:keystore.p12,keystore 和代码一起打进 jar 包,换证书就要重新打包发布,没法在服务器上自动替换。要自动化,先把 keystore 挪到 jar 外面,改成 file: 开头的绝对路径。

Spring Boot 同样可以直接用 PEM:server.ssl.certificate 指向证书链,server.ssl.certificate-private-key 指向私钥。

Spring Boot 3.2 起可以不重启换证。把证书配置成 SSL bundle 并打开 reload-on-update,Spring Boot 会在后台监视文件,内容变了就重新加载:

spring:
  ssl:
    bundle:
      jks:
        web:
          reload-on-update: true
          keystore:
            location: file:/opt/app/ssl/app.p12
            password: changeit
            type: PKCS12
server:
  ssl:
    bundle: web

bundle 的类型名叫 jks,但里面也能放 PKCS12 文件,由 type 决定。server.ssl.bundle 不能和 server.ssl.key-store 这些属性混用,改成 bundle 时要把原来的删掉。版本低于 3.2 的只能重启。Spring Boot 应用启动比 Tomcat 慢,同一台测试机上一个很小的 Spring Boot 3.5 应用重启时,HTTPS 中断约 15 秒;业务应用通常更久。

换证时最常见的三个错误

别名对不上

很多 Tomcat 教程生成 keystore 时用 keytool -alias tomcat,配置里也跟着写 certificateKeyAlias="tomcat"(Spring Boot 是 server.ssl.key-alias: tomcat)。续期后换一个工具生成 keystore,别名很可能变了,应用重启时就会报:

java.io.IOException: Alias name [tomcat] does not identify a key entry

这个错误平时看不到,因为应用正在运行,用的是内存里的旧证书。等到续期后第一次重启,应用才起不来。解决方法有两个:生成新 keystore 时指定同一个别名(openssl pkcs12 -export 加 -name tomcat),或者在 keystore 里只有一张证书时删掉配置里的别名。

密码对不上

新 keystore 的密码必须和配置里的 certificateKeystorePassword 或 server.ssl.key-store-password 一致,否则启动时报:

Failed PKCS12 integrity checking

从云厂商下载的 JKS,私钥密码有时和 keystore 密码不同,配置里会多一项 certificateKeyPassword(Spring Boot 是 server.ssl.key-password)。换成自动生成的 PKCS12 后,私钥密码和 keystore 密码相同,这一项要删掉,或者改成和 keystore 密码一致。

重启“成功”了,应用却没起来

这一个最容易漏。用 systemd 管理的 Java 服务大多是 Type=simple,systemctl restart 在进程启动后就返回,不等 Java 加载完证书。别名或密码错了的时候,systemctl restart 照样返回 0:Tomcat 进程还在,HTTPS Connector 却没有起来;Spring Boot 则是过几秒自己退出。部署脚本看到命令成功,以为换证完成,其实服务已经挂了。

所以重启命令要等到 HTTPS 真正可用才算成功,等不到就返回非 0,让自动化流程知道出了问题:

#!/bin/sh
# 用法:restart-and-wait.sh <服务名> <HTTPS 端口>
set -eu
systemctl restart "$1"
for attempt in $(seq 1 30); do
  if curl --insecure --fail --silent --max-time 1 "https://127.0.0.1:$2/" >/dev/null; then
    exit 0
  fi
  sleep 1
done
echo "$1 did not become HTTPS-ready" >&2
exit 1

--insecure 只用于本机检查端口是否起来;探测的路径换成你的应用里不需要登录、能返回 200 的地址。

第一次自动化时还要检查文件权限:Java 进程通常以非 root 用户运行,新写入的 keystore 文件要让这个用户能读。

自己写脚本:Certbot 的 deploy hook

证书由本机的 Certbot 签发时,可以把转换、替换和重启写进 deploy hook。Certbot 每次续期成功后执行它,并通过 RENEWED_LINEAGE 传入证书目录:

#!/bin/sh
set -eu
openssl pkcs12 -export \
  -in "$RENEWED_LINEAGE/fullchain.pem" \
  -inkey "$RENEWED_LINEAGE/privkey.pem" \
  -name tomcat -passout file:/etc/tomcat/keystore.pass \
  -out /opt/tomcat/ssl/tomcat.p12.new
mv /opt/tomcat/ssl/tomcat.p12.new /opt/tomcat/ssl/tomcat.p12
/usr/local/bin/restart-and-wait.sh tomcat 8443

用 acme.sh 时,先用 --install-cert 指定证书链和私钥的输出路径,把脚本里的 $RENEWED_LINEAGE/... 换成这两个路径,再通过 --reloadcmd 调用脚本。

一台服务器、一个应用时,这样就够了。服务器和应用多了以后,下面几件事都要自己补:

  • 失败恢复:上面的脚本在重启失败时,旧 keystore 已经被覆盖。要先备份,失败时换回去再重启,否则应用就停在报错状态等人处理。
  • 多台分发:Certbot 在哪台机器上续期,新证书就只在哪台。多台服务器要么各装一套 Certbot 和 hook,要么自己把证书同步过去,每台执行一遍。
  • 失败通知:Certbot 默认不发通知,hook 失败只记在日志里,没人看日志就不会知道。

用 LapseZero 自动部署到 Java 应用

LapseZero 是一个托管服务,负责签发证书、到期前自动续期,并部署到服务器和云产品上。证书是免费的 DV 证书,支持通配符,通过 DNS 验证签发:可以填 DNS 服务商的 API 密钥,也可以只加一条 CNAME。现在用的证书不用迁移,第一次部署就会把新证书写到原来的 keystore 路径上。

一台 Java 服务器只需要配置一次:添加部署目标时选「服务器」,软件选 Tomcat 或 Spring Boot,然后填三项:

  • 证书路径:配置里的 keystore 路径,Spring Boot 去掉 file: 前缀。
  • Keystore 密码:和配置里的一致。配置里写了别名的,把同一个别名也填上。
  • 部署后命令:上面的 restart-and-wait.sh。

服务器可以通过 SSH 连接,也可以装一个部署客户端,不用开放入站端口。私钥和密码都加密保存。

之后每次续期,LapseZero 自动生成 PKCS12 文件、写到原路径、执行部署后命令,前面说的三个错误都不用再操心:keystore 按你填的密码和别名生成,不会对不上;命令失败(比如应用 30 秒内没起来)时,自动换回旧 keystore 再执行一次命令,应用继续用旧证书,通知里会写明已回滚。在「生效检查」里填上应用的 HTTPS 地址,部署后还会确认线上已经换成新证书。

应用部署在多台服务器上时,每台服务器算一个部署位置,填法相同。前面的 Nginx、负载均衡和云产品也在同一个地方部署同一张证书,不用在每台机器上维护一套 hook。

目录
相关文章
|
1天前
|
存储 测试技术 索引
同等预算,向量检索吞吐最高约52倍!阿里云 Milvus EAGLE 内存索引性价比实测
阿里云Milvus EAGLE单机性能强劲:1000美元月费下达23,358 QPS(98.11%召回),吞吐超竞品最高52倍;亿级数据下仍保持高召回与低延迟,兼顾性能与成本。
36 1
|
16天前
|
负载均衡 Kubernetes 网络协议
阿里云 CLB / ALB 证书更新后,为什么网站还在用旧证书?
证书中心有了新证书,网站却还在用旧证书?检查 CLB、ALB 的监听和域名绑定,再把续期与部署一起自动化,减少逐个换证时的遗漏。
127 1
|
监控 网络安全 API
SSL 证书自动化工具怎么选:acme.sh、Certd、Certimate 和托管平台
一张通配符证书要部署到两台 Nginx、全站加速和 OSS 上,出事的往往是平时没人看的那个站点。选自动化工具,先看它能不能覆盖每个部署位置,某个位置没更新时你能不能知道。
37 0
|
负载均衡 网络协议 网络安全
阿里云免费证书只有 3 个月?自动续期并部署到 CDN / OSS
阿里云免费证书 90 天到期、不能续费、不能托管,每次都要重新申请再逐个替换 CDN、OSS、负载均衡。本文讲清手动续期流程、可选方案和自动化做法。
45 0
|
云安全 安全 网络安全
|
2天前
|
JavaScript API iOS开发
DeepSeek Harness下载、安装、配置一篇搞定(2026整理,送常用插件)
DeepSeek Harness(DSH)是DeepSeek于2026年开源的MIT协议AI Agent框架,支持插件化组装模型、工具、沙箱与UI,兼容主流大模型。本文提供免Node.js的桌面端安装包(Win/macOS),含详细图文教程及热门插件推荐。
|
16天前
|
JSON 程序员 数据格式
最新版Notepad++下载、安装、配置保姆级教程(附官网安装包)
Notepad++ 是一款免费开源、轻量快速的 Windows 文本编辑器,支持多标签、语法高亮、代码折叠与宏录制,体积小、启动快、资源占用低,兼容 x64/x32/ARM 架构,是程序员和文字工作者的高效利器。
3960 1
|
9天前
|
JavaScript 安全 前端开发
Nodejs Brotli decoder 代码执行漏洞 (CVE-2026-111497)10629
Node.js发布安全更新修复Brotli解码器高危RCE漏洞(CVE-2026-111497),建议受影响版本用户立即升级。
2058 2
|
15天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
2608 46

热门文章

最新文章