在Spring Boot应用安装SSL证书(Linux)

本文介绍如何在 Spring Boot 应用中直接配置 SSL 证书以启用 HTTPS。

适用范围

开始配置前,确保满足以下条件:

  • 证书状态:已拥有由权威机构签发的 SSL 证书。若证书即将过期或已过期,请先续费SSL证书

  • 域名匹配:确保证书能够匹配所有需保护的域名。如需添加或修改,请参见追加和更换域名

    • 精确域名:仅对指定域名生效。

      • example.com 仅对 example.com 生效。

      • www.example.com 仅对 www.example.com 生效。

    • 通配符域名:仅对其一级子域名生效。

      • *.example.com 对 www.example.coma.example.com 等一级子域名生效。

      • *.example.com 对根域名 example.com 和多级子域名 a.b.example.com 不生效。

    说明

    如需匹配多级子域名,绑定域名中需包含该域名(如 a.b.example.com),或包含相应的通配符域名(如 *.b.example.com)。

  • 服务器权限:需要使用 root 账户或一个具有 sudo 权限的账户。

  • 域名备案与解析

    • ICP 备案:域名已完成工信部 ICP 备案(仅适用于中国内地服务器)。

    • 域名解析:域名已通过 A 记录解析至服务器的公网 IP。

    说明

    可访问网络诊断分析工具,输入域名,检查 DNS 服务商解析结果备案检查项,确保满足要求。

  • 环境依赖:服务器已安装 Java 8 或更高版本。

操作步骤

步骤一:准备证书文件

  1. 进入SSL证书管理页面,在目标证书操作列单击更多进入证书详情页面,然后在下载页签中下载服务器类型JKS的证书。

    说明

    Spring Boot支持JKSPKCS12(.pfx)格式。本文以JKS为例。解压后将得到一个证书文件(如 domain.jks)和一个密码文件(jks-password.txt)。

  2. 将解压后的证书文件(.pfx或.jks)和密码文件(.txt)上传至服务器,并存放在一个安全的外部目录(/etc/ssl/myapp)。

    重要

    严禁将证书或私钥文件放置在 src/main/resources 目录下。这样做会将敏感密钥打包到应用交付物(如 JAR/WAR 文件)中,极易导致密钥泄露。

    您可以使用远程登录工具的本地文件上传功能来上传文件。例如PuTTYXshellWinSCP等工具。如果您使用的是阿里云云服务器 ECS,关于上传文件的具体操作,请参见上传或下载文件

步骤二:配置Spring Boot应用

说明

将证书密码等敏感信息硬编码在代码或配置文件中是危险的。应通过环境变量或外部安全文件进行管理。

  1. 通过export命令设置环境变量。

    # 从之前下载的密码文件中获取密码
    export SSL_KEYSTORE_PASSWORD='your_secure_password'
    # 如果私钥密码不同,同样设置
    export SSL_KEY_PASSWORD='your_key_password'
  2. 按照以下示例和说明配置application.propertiesapplication.yml文件。

    说明

    本文以Spring Boot 3.4.10版本为例。

    application.properties

    # 监听443端口
    server.port=443
    
    # --- SSL配置 ---
    # 证书文件路径,使用'file:'前缀指定外部绝对路径
    server.ssl.key-store=file:/etc/myapp/ssl/keystore.p12
    # 证书密钥库类型
    server.ssl.key-store-type=PKCS12
    # 证书别名,通常在生成JKS/P12文件时指定
    server.ssl.key-alias=mycert
    
    # --- 安全配置:密码管理 ---
    # 从环境变量读取密码,避免硬编码在配置文件中
    server.ssl.key-store-password=${SSL_KEYSTORE_PASSWORD}
    # 如果私钥密码与密钥库密码不同,也从环境变量读取
    server.ssl.key-password=${SSL_KEY_PASSWORD}
    
    # --- 安全配置:TLS协议与加密套件 ---
    # 启用安全的TLS协议版本
    server.ssl.enabled-protocols=TLSv1.2,TLSv1.3
    # 配置推荐的强加密套件
    server.ssl.ciphers=TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-RSA-AES128-GCM-SHA256
    
    # 启用HTTP/2以提升性能
    server.http2.enabled=true

    application.yml

    server:
      port: 443 # 监听443端口
    
      ssl:
        # --- SSL配置 ---
        # 证书文件路径,使用'file:'前缀指定外部绝对路径
        key-store: file:/etc/myapp/ssl/keystore.p12
        # 证书密钥库类型
        key-store-type: PKCS12
        # 证书别名,通常在生成JKS/P12文件时指定
        key-alias: mycert
    
        # --- 安全配置:密码管理 ---
        # 从环境变量读取密码,避免硬编码在配置文件中
        key-store-password: ${SSL_KEYSTORE_PASSWORD}
        # 如果私钥密码与密钥库密码不同,也从环境变量读取
        key-password: ${SSL_KEY_PASSWORD}
    
        # --- 安全配置:TLS协议与加密套件 ---
        # 启用安全的TLS协议版本
        enabled-protocols: TLSv1.2,TLSv1.3
        # 配置推荐的强加密套件
        ciphers:
          - TLS_AES_256_GCM_SHA384
          - TLS_CHACHA20_POLY1305_SHA256
          - TLS_AES_128_GCM_SHA256
          - ECDHE-RSA-AES256-GCM-SHA384
          - ECDHE-RSA-AES128-GCM-SHA256
    
      # 启用HTTP/2以提升性能
      http2:
        enabled: true

步骤三:配置系统与网络环境

确保安全组和防火墙允许外部流量访问。

  1. 在服务器终端执行以下命令,检测443端口的开放情况:

    RHEL/CentOS

    command -v nc > /dev/null 2>&1 || sudo yum install -y nc
    # 请将以下的 <当前服务器的公网 IP> 替换为当前服务器的公网 IP
    sudo ss -tlnp | grep -q ':443 ' || sudo nc -l 443 & sleep 1; nc -w 3 -vz <当前服务器的公网 IP> 443

    如果输出 Ncat: Connected to <当前服务器公网 IP>:443,则表明443端口已开放。否则需在安全组和防火墙中开放443端口。

    Debian/Ubuntu

    command -v nc > /dev/null 2>&1 || sudo apt-get install -y netcat
    # 请将以下的 <当前服务器的公网 IP> 替换为当前服务器的公网 IP
    sudo ss -tlnp | grep -q ':443 ' || sudo nc -l -p 443 & sleep 1; nc -w 3 -vz <当前服务器的公网 IP> 443

    若输出 Connection to <当前服务器公网 IP> port [tcp/https] succeeded![<当前服务器公网 IP>] 443 (https) open,则表明443端口已开放。否则需在安全组和防火墙中开放443端口。

  2. 在安全组配置开放443端口。

    重要

    若您的服务器部署在云平台,请确保其安全组已开放 443 端口 (TCP),否则外部无法访问服务。以下操作以阿里云 ECS 为例,其他云平台请参考其官方文档。

    进入云服务器ECS实例,单击目标实例名称进入实例详情页面,请参考添加安全组规则,在安全组中添加一条授权策略允许协议类型为 TCP、目的端口范围为 HTTPS(443)、授权对象任何位置(0.0.0.0/0)的规则。

  3. 在防火墙中开放443端口。

    执行以下命令,识别系统当前的防火墙服务类型:

    if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet firewalld; then
        echo "firewalld"
    elif command -v ufw >/dev/null 2>&1 && sudo ufw status | grep -qw active; then
        echo "ufw"
    elif command -v nft >/dev/null 2>&1 && sudo nft list ruleset 2>/dev/null | grep -q 'table'; then
        echo "nftables"
    elif command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet iptables; then
        echo "iptables"
    elif command -v iptables >/dev/null 2>&1 && sudo iptables -L 2>/dev/null | grep -qE 'REJECT|DROP|ACCEPT'; then
        echo "iptables"
    else
        echo "none"
    fi

    若输出为 none,则无需进一步操作。否则,请根据输出的类型(firewalldufwnftablesiptables),执行以下命令开放 443 端口:

    firewalld

    sudo firewall-cmd --permanent --add-port=443/tcp && sudo firewall-cmd --reload

    ufw

    sudo ufw allow 443/tcp

    nftables

    sudo nft add table inet filter 2>/dev/null
    sudo nft add chain inet filter input '{ type filter hook input priority 0; }' 2>/dev/null
    sudo nft add rule inet filter input tcp dport 443 counter accept 2>/dev/null

    iptables

    sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

    为避免 iptables 规则在系统重启后失效,请执行以下命令持久化 iptables 规则:

    RHEL/CentOS
    sudo yum install -y iptables-services
    sudo service iptables save
    Debian/Ubuntu
    sudo apt-get install -y iptables-persistent
    sudo iptables-save | sudo tee /etc/iptables/rules.v4 >/dev/null

步骤四:启动应用

进入Spring Boot项目根目录,请根据构建工具,在项目根目录下执行相应命令以重启应用。

开发/测试环境 (使用构建插件)

  • Maven

    mvn spring-boot:run
  • Gradle

    gradle bootRun

生产环境(作为独立JAR包运行)

生产环境通常将应用打包为.jar文件运行。您需要先停止旧的进程,然后使用java -jar命令重新启动。

# 1. 找到并停止正在运行的应用进程 (PID)
# ps -ef | grep your-app-name.jar
# kill <PID>
#
# 2. 重新启动应用,若需增加相关 JVM 参数,请在&之前继续补充。
nohup java -jar /path/to/your-app-name.jar &
说明

重启后,请检查应用日志,确保SSL证书已成功加载且服务在HTTPS端口正常启动。

步骤五:验证部署结果

  1. 请通过 HTTPS 访问您已绑定证书的域名(如 https://yourdomain.comyourdomain.com 需替换为实际域名)。

  2. 若浏览器地址栏显示安全锁图标,说明证书已成功部署。如访问异常或未显示安全锁,请先清除浏览器缓存或使用无痕(隐私)模式重试。

    image

    Chrome 浏览器自 117 版本起,地址栏中的image已被新的image替代,需单击该图标后查看安全锁信息。

说明

如仍有问题,请参考常见问题进行排查。

应用于生产环境

在生产环境部署时,遵循以下最佳实践可提升安全性、稳定性和可维护性:

  • 使用非管理员权限用户运行

    为应用创建专用的、低权限的系统用户,切勿使用拥有管理员权限的账户运行应用。

    说明

    建议使用网关层配置 SSL的方案,即将证书部署在负载均衡SLBNginx等反向代理上,由其终结 HTTPS 流量,再将解密后的 HTTP 流量转发到后端应用。

  • 凭证外部化管理

    切勿将密码等敏感信息硬编码在代码或配置文件中。使用环境变量、Vault 或云服务商提供的密钥管理服务来注入凭证。

  • 启用 HTTP 到 HTTPS 强制跳转

    确保所有通过 HTTP 访问的流量都被自动重定向到 HTTPS,防止中间人攻击。

  • 配置现代 TLS 协议

    在服务器配置中禁用老旧且不安全的协议(如 SSLv3, TLSv1.0, TLSv1.1),仅启用 TLSv1.2 和 TLSv1.3。

  • 证书监控与自动续期

    建议在证书部署完成后,为域名开启域名监控功能。阿里云将自动检测证书有效期,并在证书到期前发送提醒,帮助您及时续期,避免服务中断。具体操作请参见购买并开启公网域名监控

常见问题

安装或更新证书后,证书未生效或 HTTPS 无法访问

常见原因如下:

  • 域名未完成备案。请参见ICP备案流程

  • 服务器安全组或防火墙未开放 443 端口。请参见配置系统与网络环境

  • 证书的绑定域名未包含当前访问的域名。请参见域名匹配

  • 修改 Spring Boot 配置文件后,未重启Spring Boot服务。具体操作可参见步骤四:启动应用

  • 证书文件未正确替换,或 Spring Boot 配置未正确指定证书路径。请检查 Spring Boot 配置文件和所用证书文件是否为最新且有效。

  • 域名已接入 CDN、SLB 或 WAF 等云产品,但未在相应产品中安装证书。请参阅流量经过多个云产品时证书的部署位置完成相关操作。

  • 当前域名的 DNS 解析指向多台服务器,但证书仅在部分服务器上安装。需分别在每个服务器中安装证书。

如何更新(替换)Spring Boot 应用中已安装的 SSL 证书

请先备份服务器上原有的证书文件(.pfx或.jks,以及.txt文件),然后登录数字证书管理服务控制台,下载新的证书文件,并上传到目标服务器覆盖原有文件(确保路径和文件名一致)。最后,重启Spring Boot应用,使新证书生效。