Spring Boot/Tomcat多域名SSL证书配置方案咨询
Absolutely, using TomcatServletWebServerFactory (the updated replacement for TomcatEmbeddedServletContainerFactory in Spring Boot 2.x and later) is a totally solid solution for this scenario. I’ve set up exactly this kind of configuration for a few production projects, so let me walk you through how to get it working smoothly.
First, Prep Your Signed Certificates
正规CAs (like Let’s Encrypt, DigiCert, etc.) typically provide either a combined PKCS12 file or separate .crt and .key files. If you get separate files, convert them to PKCS12 first with this common OpenSSL command:
openssl pkcs12 -export -in your-domain.crt -inkey your-domain.key -out your-domain.p12 -name "your-domain-alias"
You’ll be prompted to set a keystore password—make sure you note this down for later. Repeat this step for your second domain to get two distinct PKCS12 files (separate files are easier to manage than merging into one keystore).
Configure the Tomcat Web Server Factory
Create a Spring configuration class to define the Tomcat bean, where you’ll set up SSL connectors. The most practical approach here is to use SNI (Server Name Indication)—this lets you serve multiple domains over the same HTTPS port (8443) by having Tomcat return the correct certificate based on the incoming domain name. Here’s a working code example:
import org.apache.catalina.connector.Connector; import org.apache.catalina.Context; 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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TomcatSslConfig { @Bean public TomcatServletWebServerFactory servletContainer() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() { @Override protected void postProcessContext(Context context) { // Optional: Force all HTTP traffic to redirect to HTTPS SecurityConstraint securityConstraint = new SecurityConstraint(); securityConstraint.setUserConstraint("CONFIDENTIAL"); SecurityCollection collection = new SecurityCollection(); collection.addPattern("/*"); securityConstraint.addCollection(collection); context.addConstraint(securityConstraint); } }; // Create a single HTTPS connector for SNI Connector sniConnector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); org.apache.coyote.http11.Http11NioProtocol protocol = (org.apache.coyote.http11.Http11NioProtocol) sniConnector.getProtocolHandler(); sniConnector.setPort(8443); sniConnector.setSecure(true); sniConnector.setScheme("https"); protocol.setSSLEnabled(true); // Set your default domain's certificate (fallback if SNI doesn't match) protocol.setKeystoreFile("/absolute/path/to/first-domain.p12"); protocol.setKeystorePass("your-first-keystore-password"); protocol.setKeystoreType("PKCS12"); protocol.setKeyAlias("first-domain-alias"); protocol.setSslProtocol("TLSv1.2"); // Enforce modern, secure TLS versions // Add SNI config for your second domain org.apache.tomcat.util.net.SSLHostConfig sniHostConfig = new org.apache.tomcat.util.net.SSLHostConfig(); sniHostConfig.setHostName("your-second-domain.com"); org.apache.tomcat.util.net.SSLHostConfigCertificate secondDomainCert = new org.apache.tomcat.util.net.SSLHostConfigCertificate(sniHostConfig, org.apache.tomcat.util.net.SSLHostConfigCertificate.Type.RSA); secondDomainCert.setCertificateKeystoreFile("/absolute/path/to/second-domain.p12"); secondDomainCert.setCertificateKeystorePassword("your-second-keystore-password"); secondDomainCert.setCertificateKeystoreType("PKCS12"); secondDomainCert.setCertificateKeyAlias("second-domain-alias"); sniHostConfig.addCertificate(secondDomainCert); protocol.addSslHostConfig(sniHostConfig); // Add the SNI connector to Tomcat tomcat.addAdditionalTomcatConnectors(sniConnector); return tomcat; } }
Clean Up Your application.properties
Since we’re handling SSL configuration in code now, remove all the old server.ssl.* lines from your properties file to avoid configuration conflicts.
Test It Out
Fire up your Spring Boot app, then:
- Visit both domains in a browser—you should see the valid, trusted certificate for each without any security warnings.
- Use
curlto verify from the command line:curl -v https://your-first-domain.com:8443 curl -v https://your-second-domain.com:8443
Quick Notes to Keep In Mind
- Firewall Access: Make sure your server’s firewall allows incoming traffic on port 8443.
- Certificate Renewal: If you’re using a free CA like Let’s Encrypt, set up auto-renewal with Certbot, then restart your Spring Boot app (or look into Tomcat’s hot-reload for SSL certificates if you want to avoid restarts).
- Spring Boot 1.x Compatibility: If you’re still on Spring Boot 1.x, swap
TomcatServletWebServerFactorywithTomcatEmbeddedServletContainerFactory—the rest of the logic stays mostly the same.
内容的提问来源于stack exchange,提问作者Vasily Avilov

