【发布时间】:2022-01-13 15:09:26
【问题描述】:
我需要确保我的客户端支持 SNI 并且可以正常工作。为此,我想启动一些需要来自客户端的主机名的虚拟服务器(带有嵌入式 Tomcat 9 的 Spring Boot 应用程序)。问题是如何强制 Spring Boot 嵌入式 Tomcat 要求来自客户端的 SNI? 我已经读过要做到这一点,我们需要向服务器提供 2 个(或更多)证书。
我试图从这个topic 中学习示例。但这对我不起作用。
我生成了 2 个密钥库 mycompany1.keystore 和 mycompany2.keystore,每个密钥库都有 1 个证书。还有 1 个信任库 mycompany.truststore 存储这两个证书。证书有CNmy.hostname.com和my.another.hostname.com。
这是我配置嵌入式 tomcat 的方式:
@Component
public class MultipleHostsTomcatFactory {
@Value("${abc.com.key-store}")
String abcComKeyStore;
@Value("${xyz.com.key-store}")
String xyzComKeyStore;
@Value("${server.port}")
int serverPort;
@Value("${server.http.port:8080}")
private int httpPort;
@Bean
public ServletWebServerFactory servletContainer() throws Exception {
TomcatServletWebServerFactory factor = new TomcatServletWebServerFactory();
factor.addAdditionalTomcatConnectors(createSSLConnectorForMultipleHosts());
return factor;
}
private Connector createSSLConnectorForMultipleHosts() {
Connector connector = null;
try {
connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("https");
connector.setSecure(true);
connector.setProperty("SSLEnabled", "true");
connector.setProperty("defaultSSLHostConfigName", /*"*.abc.com"*/ "*.hostname.com");
connector.setPort(8444);
// *.abc.com
SSLHostConfig sslHostConfig = new SSLHostConfig();
sslHostConfig.setHostName("*.abc.com");
SSLHostConfigCertificate sslHostConfigCertificate = new SSLHostConfigCertificate(sslHostConfig, SSLHostConfigCertificate.Type.EC);
sslHostConfigCertificate.setCertificateKeystoreFile(abcComKeyStore);
sslHostConfig.addCertificate(sslHostConfigCertificate);
connector.addSslHostConfig(sslHostConfig);
// *.xyz.com
sslHostConfig = new SSLHostConfig();
sslHostConfig.setHostName("*.xyz.com");
sslHostConfigCertificate = new SSLHostConfigCertificate(sslHostConfig, SSLHostConfigCertificate.Type.EC);
sslHostConfigCertificate.setCertificateKeystoreFile(xyzComKeyStore);
sslHostConfig.addCertificate(sslHostConfigCertificate);
connector.addSslHostConfig(sslHostConfig);
} catch (Exception e) {
System.out.println("Catched exception!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
e.printStackTrace();
}
return connector;
}
}
此代码基于此topic。 但我有一个错误:
2022-01-13 16:10:21.301 ERROR 22364 --- [ main] org.apache.catalina.util.LifecycleBase : Failed to initialize component [Connector[HTTP/1.1-8444]]
org.apache.catalina.LifecycleException: Protocol handler initialization failed
...
Caused by: java.lang.IllegalArgumentException: Keystore was tampered with, or password was incorrect
...
Caused by: java.io.IOException: Keystore was tampered with, or password was incorrect
...
Caused by: java.security.UnrecoverableKeyException: Password verification failed
我好像错过了什么。
那么,如何强制嵌入式 Tomcat 启用 SNI?
【问题讨论】:
-
请尝试将
abc.com和xyz.com替换为my.host...始终(而不是混合;) -
@xerx593,我将它们替换为
my.hostname.com和my.another.hostname.com。没有帮助。 -
那么 defaultSSLHostConfigName 呢?
-
@xerx593,更改为
my.hostname.com和my.another.hostname.com(两种变体都试过) - 没有帮助。关于这个错误的问题是:spring 验证什么?我没有配置任何密码。 -
您对这些密钥库使用了什么格式?尝试使用
setCertificateKeystoreType设置正确的。
标签: java spring-boot tomcat sni