SpringBoot配置SSL证书完整教程:3种方式实现HTTPS访问

a
admin
作者
2026-08-13
发布日期
约 22 分钟
阅读时间

SpringBoot配置SSL证书完整教程:3种方式实现HTTPS访问

SpringBoot项目默认跑HTTP,生产环境必须上HTTPS。SpringBoot配置SSL证书有三种主流方式,从最简单的内嵌配置到最灵活的反向代理,本文逐一讲解。先申请一张SSL证书,建议在 sslmianfei.com 在线免费申请。

准备工作:获取SSL证书

不管用哪种方式,都要先有SSL证书文件。SpringBoot需要的是PKCS12(.p12)或JKS(.jks)格式的证书,而CA机构默认下发的是PEM格式(.crt + .key)。

申请证书

sslmianfei.com 申请ZeroSSL免费证书,下载得到:

  • fullchain.crt(证书文件,包含服务器证书和中间证书)
  • private.key(私钥文件)

转换为PKCS12格式

SpringBoot推荐用PKCS12格式,用OpenSSL转换:

openssl pkcs12 -export -in fullchain.crt -inkey private.key -out yourdomain.p12 -name yourdomain -passout pass:yourpassword

参数说明:

  • -in fullchain.crt:证书文件(必须是包含中间证书的fullchain)
  • -inkey private.key:私钥文件
  • -out yourdomain.p12:输出的PKCS12文件
  • -name yourdomain:证书别名
  • -passout pass:yourpassword:设置p12文件的密码

执行后会生成 yourdomain.p12 文件,这就是SpringBoot要用的证书文件。

方式一:SpringBoot内嵌Tomcat配置SSL(最简单)

这是最直接的方式,把证书直接配置到SpringBoot内嵌的Tomcat中。

第一步:放置证书文件

yourdomain.p12 放到SpringBoot项目的 src/main/resources/ 目录下:

your-project/
├── src/
│   └── main/
│       ├── java/
│       └── resources/
│           ├── application.yml
│           └── yourdomain.p12    ← 证书文件放这里
└── pom.xml

第二步:配置application.yml

server:
  port: 443
  ssl:
    key-store: classpath:yourdomain.p12
    key-store-password: yourpassword
    key-store-type: PKCS12
    key-alias: yourdomain

如果是 application.properties 格式:

server.port=443
server.ssl.key-store=classpath:yourdomain.p12
server.ssl.key-store-password=yourpassword
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=yourdomain

第三步:启动项目验证

启动SpringBoot项目,浏览器访问 https://yourdomain.com,应该能看到绿色小锁。

验证配置:用 SSL证书配置检测工具 在线检测证书链是否完整、TLS版本是否安全。

配置HTTP自动跳转HTTPS

默认情况下用户访问 http://yourdomain.com 会访问失败(80端口没监听)。需要配置HTTP自动跳转到HTTPS。

新增配置类

import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HttpToHttpsConfig {

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
            @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(80);
        connector.setSecure(false);
        connector.setRedirectPort(443);
        return connector;
    }
}

这样配置后

  • 80端口监听HTTP请求
  • 443端口监听HTTPS请求
  • 所有HTTP请求自动301跳转到HTTPS

方式二:Nginx反向代理SpringBoot(推荐生产环境)

生产环境推荐用Nginx做反向代理,Nginx处理HTTPS,SpringBoot只跑HTTP。这样配置更灵活,证书更新不用重启Java应用。

架构说明

用户 --HTTPS--> Nginx(443) --HTTP--> SpringBoot(8080)

第一步:Nginx配置HTTPS

server {
    listen 443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;

    ssl_certificate /etc/nginx/ssl/fullchain.crt;
    ssl_certificate_key /etc/nginx/ssl/private.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# HTTP 301跳转到HTTPS
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

第二步:SpringBoot配置

SpringBoot只需跑HTTP,不需要配置SSL:

server:
  port: 8080

第三步:处理Forwarded头

为了让SpringBoot正确识别用户的真实IP和协议,需要配置Tomcat的RemoteIpValve:

server:
  port: 8080
  tomcat:
    remoteip:
      remote-ip-header: X-Real-IP
      protocol-header: X-Forwarded-Proto

或在配置类中:

@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> remoteIpCustomizer() {
    return factory -> factory.addContextCustomizers(context -> {
        RemoteIpValve remoteIpValve = new RemoteIpValve();
        remoteIpValve.setRemoteIpHeader("X-Real-IP");
        remoteIpValve.setProtocolHeader("X-Forwarded-Proto");
        context.getPipeline().addValve(remoteIpValve);
    });
}

这种方式的优势

  • 证书更新不用重启Java应用
  • Nginx可以做静态资源缓存、限流等
  • Nginx处理HTTPS性能更高
  • 支持HTTP/2、HTTP/3等新协议
  • 配置更灵活

方式三:使用Let’s Encrypt自动续期

如果用Let’s Encrypt证书,可以配合acme.sh实现自动申请和续期,SpringBoot完全不用关心证书。

第一步:用acme.sh申请证书

# 安装acme.sh
curl https://get.acme.sh | sh

# 申请证书(DNS验证)
acme.sh --issue --dns dns_ali -d yourdomain.com -d www.yourdomain.com

# 安装证书到Nginx
acme.sh --install-cert -d yourdomain.com \
    --key-file /etc/nginx/ssl/private.key \
    --fullchain-file /etc/nginx/ssl/fullchain.crt \
    --reloadcmd "systemctl reload nginx"

第二步:配置自动续期

acme.sh会自动创建cron定时任务,每60天自动续期一次:

# 查看定时任务
crontab -l | grep acme

# 输出示例
0 0 * * * /root/.acme.sh/acme.sh --cron --home /root/.acme.sh

第三步:SpringBoot + Nginx配置

参考方式二的Nginx反向代理配置即可。

多域名配置

如果SpringBoot要支持多个域名,可以配置多个证书。

Nginx配置多域名(推荐)

# 域名1
server {
    listen 443 ssl http2;
    server_name site1.com;
    ssl_certificate /etc/nginx/ssl/site1.crt;
    ssl_certificate_key /etc/nginx/ssl/site1.key;
    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

# 域名2
server {
    listen 443 ssl http2;
    server_name site2.com;
    ssl_certificate /etc/nginx/ssl/site2.crt;
    ssl_certificate_key /etc/nginx/ssl/site2.key;
    location / {
        proxy_pass http://127.0.0.1:8081;
    }
}

SpringBoot内嵌配置多域名(不推荐)

SpringBoot内嵌Tomcat配置多域名HTTPS比较复杂,需要自定义SNI配置,不推荐这种方式,建议用Nginx反向代理。

常见问题排查

问题一:启动报错”Cannot recover key”

原因:p12文件密码错误,或key-alias不匹配。

解决

# 查看p12文件内容
keytool -list -v -keystore yourdomain.p12 -storepass yourpassword

# 确认alias名称
# 如果alias不是yourdomain,修改application.yml中的key-alias

问题二:启动报错”DerInputStream.getLength”

原因:p12文件损坏,或文件路径错误。

解决

  • 确认p12文件在 src/main/resources/ 目录下
  • 重新生成p12文件
  • 检查文件路径配置(classpath: vs file:)

问题三:浏览器报”证书不受信任”

原因:证书链不完整,缺少中间证书。

解决

问题四:HTTP跳转HTTPS后出现重定向循环

原因:Nginx反向代理模式下,SpringBoot收到了HTTP请求(Nginx解密后是HTTP),又触发跳转到HTTPS,形成循环。

解决:配置 X-Forwarded-Proto 头,让SpringBoot识别原始协议是HTTPS。

server:
  tomcat:
    remoteip:
      protocol-header: X-Forwarded-Proto

问题五:SpringBoot启动后443端口被占用

原因:80或443端口被其他服务占用(如Nginx、Apache)。

解决

# Linux查看端口占用
netstat -tlnp | grep :443

# 停止占用443端口的服务
systemctl stop nginx
# 或
systemctl stop apache2

性能优化建议

启用HTTP/2

server:
  http2:
    enabled: true

注意:SpringBoot 2.x开始支持HTTP/2,需要Java 9+和Tomcat 9+。

配置SSL Session缓存

server:
  ssl:
    enabled-protocols: TLSv1.2,TLSv1.3
    ciphers: ECDHE-RSA-AES128-GCM-SHA256,ECDHE-RSA-AES256-GCM-SHA384

选择合适的证书

  • 单域名:DV证书足够,免费申请
  • 多个子域名:通配符证书,省事
  • 多个域名:多域名证书

sslmianfei.com 可以申请以上所有类型的免费证书。

三种方式对比

方式一:SpringBoot内嵌配置

  • 优点:配置简单,无需Nginx
  • 缺点:证书更新需要重启应用,性能不如Nginx
  • 适合:小型项目、开发测试

方式二:Nginx反向代理

  • 优点:配置灵活,证书更新不影响应用,性能高
  • 缺点:需要额外维护Nginx
  • 适合:生产环境、中大型项目

方式三:Let’s Encrypt自动续期

  • 优点:完全自动化,无需手动维护
  • 缺点:需要服务器权限
  • 适合:长期运行的生产项目

总结

SpringBoot配置SSL证书的3种方式

  • 方式一:内嵌Tomcat配置,简单直接,适合小型项目
  • 方式二:Nginx反向代理,灵活高效,推荐生产环境
  • 方式三:acme.sh自动续期,长期免维护

核心步骤

  1. sslmianfei.com 申请免费SSL证书
  2. 用OpenSSL将PEM转换为PKCS12格式(仅方式一需要)
  3. 配置SpringBoot或Nginx
  4. 配置HTTP自动跳转HTTPS
  5. SSL检测工具 验证配置

推荐方案:生产环境用Nginx反向代理 + acme.sh自动续期,开发测试用SpringBoot内嵌配置。

本文到此结束