SpringBoot配置SSL证书完整教程:3种方式实现HTTPS访问
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:)
问题三:浏览器报”证书不受信任”
原因:证书链不完整,缺少中间证书。
解决:
- •确认转换p12时用的是fullchain.crt而不是单独的服务器证书
- •用 SSL证书配置检测工具 检测证书链
问题四: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自动续期,长期免维护
核心步骤:
- 在 sslmianfei.com 申请免费SSL证书
- 用OpenSSL将PEM转换为PKCS12格式(仅方式一需要)
- 配置SpringBoot或Nginx
- 配置HTTP自动跳转HTTPS
- 用 SSL检测工具 验证配置
推荐方案:生产环境用Nginx反向代理 + acme.sh自动续期,开发测试用SpringBoot内嵌配置。