本教程详细指导如何在spring Boot应用中集成goDaddy ssl证书,实现httpS安全通信。内容涵盖使用OpenSSL生成私钥和CSR、获取GoDaddy证书、将证书转换为PKCS12格式,以及在spring boot嵌入式tomcat中配置SSL连接器和强制https重定向。教程强调了现代Java环境中使用PKCS12格式的优势,并提供了清晰的代码示例和最佳实践建议。
引言
在现代web应用开发中,确保数据传输的安全性至关重要。spring boot应用通常使用嵌入式tomcat服务器,而配置ssl/tls是实现https安全通信的关键一步。本教程将详细介绍如何利用godaddy颁发的ssl证书,在spring boot嵌入式tomcat环境中进行配置,从证书的生成、转换到最终的应用集成,提供一套完整的实践指南。
SSL证书准备:从GoDaddy到PKCS12
配置HTTPS的第一步是准备好SSL证书文件。GoDaddy通常提供PEM格式的证书。为了在Java环境中使用,我们通常需要将其转换为Java KeyStore (JKS) 或 PKCS12 格式。现代Java版本更推荐使用PKCS12格式。
1. 生成私钥和证书签名请求 (CSR)
首先,使用OpenSSL工具生成私钥(.key文件)和证书签名请求(.csr文件)。CSR是向证书颁发机构(CA,如GoDaddy)申请SSL证书的必要文件。
openssl req -new -newkey rsa:2048 -nodes -keyout website_name_here.key -out website_name_here.csr
执行此命令后,系统会提示您输入一系列信息,用于生成CSR。请确保“Common Name (e.g. server FQDN or YOUR name)”字段填写您的域名,例如 website_name_here.co。
生成的文件:
- website_name_here.key: 您的私钥文件。请务必妥善保管,切勿泄露。
- website_name_here.csr: 证书签名请求文件。
2. 获取GoDaddy SSL证书
将生成的 website_name_here.csr 文件提交给GoDaddy。GoDaddy验证您的域名所有权后,会颁发SSL证书。您通常会收到一个包含多个文件的压缩包,其中可能包括:
- 您的服务器证书(例如 your_domain.crt 或 gd_bundle-g2-g1.crt 中的第一个证书)。
- 中间证书链(例如 gd_bundle-g2-g1.crt)。
- 根证书(通常包含在中间证书链文件中)。
请确保将这些文件下载并解压到您的工作目录。通常,GoDaddy提供的证书是PEM格式。
3. 关键步骤:转换为PKCS12格式
这是将OpenSSL生成的私钥和GoDaddy颁发的证书合并为Java可识别的密钥库格式的关键一步。PKCS12(.p12)是一种行业标准格式,现代Java版本(Java 8u60及更高版本,以及Java 9+)默认支持并推荐使用。
openssl pkcs12 -export -in your_server_certificate.crt -inkey website_name_here.key -out website_name_here.p12 -name website_name_here.co -CAfile gd_bundle-g2-g1.crt -caname root
参数说明:
- -in your_server_certificate.crt: 您的服务器证书文件。如果GoDaddy提供的是一个包含服务器证书和中间证书的bundle文件,您可能需要将其拆分或确保此文件包含您的服务器证书。通常GoDaddy会提供一个单独的域名证书文件,以及一个包含中间证书和根证书的bundle文件。
- -inkey website_name_here.key: 步骤1中生成的私钥文件。
- -out website_name_here.p12: 将要生成的PKCS12密钥库文件。
- -name website_name_here.co: 证书的别名(alias),在Spring Boot配置中会用到。这里使用您的域名作为别名。
- -CAfile gd_bundle-g2-g1.crt: GoDaddy提供的中间证书链文件。这个文件通常包含多个证书,用于构建信任链。
- -caname root: (可选)为CA证书链指定一个别名。
执行此命令时,系统会提示您设置一个导出密码(Export Password)。此密码将用于保护 website_name_here.p12 文件,并在Spring Boot配置中引用。
4. (可选/不推荐)转换为JKS格式的注意事项
在Java 8u60之前的版本中,JKS(Java KeyStore)是Java的默认密钥库格式。虽然您可以使用 keytool 将PKCS12文件进一步转换为JKS格式,但对于现代Java应用,这通常是不必要的,并且不推荐。
# 仅当您需要JKS格式时才执行此步骤,但强烈建议直接使用PKCS12 keytool -importkeystore -deststorepass pwd_here -destkeystore website_name_here.jks -srckeystore website_name_here.p12 -srcstoretype PKCS12
重要提示:
- Java 9及更高版本默认创建和使用PKCS12格式的密钥库。
- Java 8u60及更高版本可以直接读取PKCS12格式的密钥库。
- JKS格式是oracle的专有格式,而PKCS12是行业标准。使用PKCS12可以提高兼容性和安全性。
因此,建议直接在Spring Boot中使用 .p12 文件,避免额外的转换步骤。
Spring Boot嵌入式Tomcat配置
在Spring Boot应用中配置SSL,主要是通过自定义 TomcatServletWebServerFactory 来实现。这允许我们配置Tomcat连接器,指向我们准备好的密钥库文件。
1. 自定义WebServerFactory
创建一个实现 WebServerFactoryCustomizer<TomcatServletWebServerFactory> 接口的组件,用于自定义Tomcat服务器的配置。
import lombok.SneakyThrows; import org.apache.catalina.connector.Connector; import org.apache.coyote.http11.Http11NioProtocol; import org.apache.tomcat.util.descriptor.web.SecurityCollection; import org.apache.tomcat.util.descriptor.web.SecurityConstraint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.stereotype.Component; import java.net.InetAddress; import java.util.Optional; @Component public class TomcatEmbedServerCustomConfiguration implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { private static final Logger logger = LoggerFactory.getLogger(TomcatEmbedServerCustomConfiguration.class); // 假设这些是您的配置存储库,实际项目中应从配置文件或环境变量获取 // IWebApplicationServerSettingsRepository appSettinsRepository; // ApplicationHttpsSettingsEntityRepository applicationHttpsSettingsEntityRepository; // public TomcatEmbedServerCustomConfiguration(IWebApplicationServerSettingsRepository appSettinsRepository, ApplicationHttpsSettingsEntityRepository applicationHttpsSettingsEntityRepository) { // this.appSettinsRepository = appSettinsRepository; // this.applicationHttpsSettingsEntityRepository = applicationHttpsSettingsEntityRepository; // } @SneakyThrows @Override public void customize(TomcatServletWebServerFactory factory) { logger.info("Setting the Tomcat specific configurations. started"); try { // 假设从配置或数据库获取端口和地址 // Optional<WebApplicationServerSettingEntity> serverSettingEntity = appSettinsRepository.findById(1); // if (serverSettingEntity.isPresent()) { // factory.setPort(serverSettingEntity.get().getPort().getPORT()); // factory.setAddress(InetAddress.getByName(serverSettingEntity.get().getHost())); // } // 示例:设置默认HTTP端口和地址 factory.setPort(8080); // 默认HTTP端口 factory.setAddress(InetAddress.getByName("0.0.0.0")); // 默认监听所有接口 factory.setServerHeader("Server header of tomcat"); // HTTPS Settings - Begin // 假设从配置或数据库获取HTTPS设置 boolean useHttps = true; // 示例:启用HTTPS String keyStorePath = "file:///c:/trash/website_name_here.p12"; // 指向您的PKCS12文件路径 String keyStorePassword = "pwd_here"; // PKCS12文件的密码 String keyAlias = "website_name_here.co"; // 证书别名,与openssl pkcs12 -name 参数一致 int httpsPort = 8443; // HTTPS端口 if (useHttps) { logger.info("Setting HTTPS settings...."); factory.addAdditionalTomcatConnectors(createSslConnector(keyStorePath, keyStorePassword, keyAlias, httpsPort)); factory.addContextCustomizers(context -> { logger.info("Setting HTTPS settings....setting..."); SecurityConstraint securityConstraint = new SecurityConstraint(); securityConstraint.setUserConstraint("CONFIDENTIAL"); SecurityCollection collection = new SecurityCollection(); collection.addPattern("/*"); securityConstraint.addCollection(collection); context.addConstraint(securityConstraint); logger.info("Setting HTTPS settings....setting...Done"); }); } logger.info("Setting HTTPS settings....End"); // HTTPS Settings - end logger.info("Tomcat Server Configuration Host=[" + factory.getAddress() + "] Port=[" + factory.getPort() + "]"); logger.info("Setting the Tomcat specific configurations. ended"); } catch (Exception e) { logger.error(e.getMessage()); throw e; } } // HTTPS Settings - Begin private Connector createSslConnector(String keyStorePath, String keyStorePassword, String keyAlias, int httpsPort) { logger.info("Creating SSL Connector..."); Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler(); connector.setScheme("https"); connector.setSecure(true); connector.setPort(httpsPort); // 设置HTTPS端口 protocol.setSSLEnabled(true); protocol.setKeystoreFile(keyStorePath); // 指定PKCS12文件路径 protocol.setKeystorePass(keyStorePassword); // PKCS12文件密码 protocol.setKeyAlias(keyAlias); // 证书别名 logger.info("Creating SSL Connector...Done"); return connector; } // HTTPS Settings - End }
在上述代码中,createSslConnector 方法负责创建并配置一个SSL连接器。关键配置项包括:
- protocol.setKeystoreFile(): 指定PKCS12密钥库文件的路径。请确保路径正确,可以是绝对路径或类路径下的相对路径。
- protocol.setKeystorePass(): 指定PKCS12文件的密码,即您在 openssl pkcs12 -export 命令中设置的导出密码。
- protocol.setKeyAlias(): 指定证书的别名,与您在 openssl pkcs12 -export 命令中 -name 参数设置的值一致。
2. HTTP到HTTPS重定向 (可选)
为了确保所有流量都通过HTTPS进行,您可以配置Tomcat将所有HTTP请求重定向到HTTPS。这可以通过添加一个 SecurityConstraint 来实现。
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 SecurityConfig { @Bean public TomcatServletWebServerFactory httpsredirectConfig() { return new TomcatServletWebServerFactory() { @Override protected void postProcessContext(Context context) { SecurityConstraint securityConstraint = new SecurityConstraint(); securityConstraint.setUserConstraint("CONFIDENTIAL"); // 要求使用保密传输(即HTTPS) SecurityCollection collection = new SecurityCollection(); collection.addPattern("/*"); // 匹配所有URL securityConstraint.addCollection(collection); context.addConstraint(securityConstraint); } }; } }
这个配置会在Tomcat启动时,为所有请求添加一个安全约束,强制使用HTTPS。当HTTP请求到达时,Tomcat会自动将其重定向到相应的HTTPS端口。
注意事项与最佳实践
- 密钥库安全:私钥文件(.key)和PKCS12密钥库文件(.p12)包含敏感信息,必须严格保护。不要将其提交到版本控制系统,或以不安全的方式存储。在生产环境中,应使用环境变量、Vault等安全机制来管理密钥库密码。
- 证书链完整性:确保您的PKCS12文件包含了完整的证书链(服务器证书、中间证书、根证书)。如果缺少中间证书,客户端可能会报告证书不信任的错误。openssl pkcs12 -export 命令的 -CAfile 参数就是用于包含中间证书链的。
- 别名一致性:在 openssl pkcs12 -export 中使用的 -name 参数(证书别名)必须与Spring Boot配置中 protocol.setKeyAlias() 的值完全一致。
- 路径正确性:protocol.setKeystoreFile() 中指定的路径必须是Tomcat进程可以访问到的有效路径。
- 自动续期:SSL证书通常有有效期,需要定期续期。考虑使用自动化工具或流程来管理证书的续期和部署,以避免因证书过期导致的服务中断。
- 生产环境配置:在生产环境中,通常会将密钥库文件放置在应用外部的安全位置,并通过配置属性(如 application.properties 或 application.yml)或环境变量来引用其路径和密码,而不是硬编码在代码中。
总结
通过遵循本教程的步骤,您应该能够在Spring Boot嵌入式Tomcat服务器中成功配置GoDaddy SSL证书,实现安全的HTTPS通信。关键在于正确使用OpenSSL生成和转换证书,并将其整合到Spring Boot的Tomcat配置中。请始终牢记安全最佳实践,以确保您的Web应用在生产环境中安全可靠地运行。