使用了 HTTPS 连接 Elasticsearch,但通常本地环境使用的是自签名证书,Java 默认会验证证书链,因此会出现 PKIX path building failed 等证书信任错误。
要解决“如何信任”的问题,有以下几种常见方案:
1. 将自签名证书导入 JVM 的信任库(推荐用于开发/测试)
步骤:
-
导出 Elasticsearch 的证书(以 PEM 格式为例)
openssl s_client -connect localhost:9200 -showcerts </dev/null 2>/dev/null | \ openssl x509 -outform PEM > elastic-cert.pem -
导入到 Java 的 cacerts 信任库
keytool -import -alias elasticsearch -keystore $JAVA_HOME/lib/security/cacerts \ -file elastic-cert.pem -storepass changeit -noprompt默认密码是
changeit,若使用自定义信任库请替换路径。 -
重启应用,证书即被信任。
2. 使用自定义 TrustStore(更灵活)
在 Spring Boot 中配置专用信任库:
-
创建自己的 truststore
keytool -import -alias elasticsearch -keystore mytruststore.jks \ -file elastic-cert.pem -storepass mypassword -
在
application.yml或application.properties中指定spring.elasticsearch.restclient.ssl.truststore=classpath:mytruststore.jks spring.elasticsearch.restclient.ssl.truststore-password=mypassword注意:Spring Boot 2.x 中配置项为
spring.elasticsearch.restclient.ssl.*,如果是 Spring Data Elasticsearch 4.x+ 使用 RestClient,配置方式可能略有不同。如果是 Spring Boot 3.x 且使用
RestClient自动配置,可以添加:spring.elasticsearch.ssl.bundle=my-bundle spring.elasticsearch.ssl.bundle.my-bundle.truststore.location=classpath:mytruststore.jks spring.elasticsearch.ssl.bundle.my-bundle.truststore.password=mypassword
3. 禁用 SSL 验证(仅限开发环境,极不推荐生产)
创建 RestClient 自定义配置,绕过证书校验:
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration;
@Configuration
public class ElasticsearchConfig extends ElasticsearchConfiguration {
@Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder()
.connectedTo("localhost:9200")
.usingSsl(buildSSLContext())
.withBasicAuth("elastic", "2DwqxCaVFFWhXBdvk+6x")
.build();
}
private SSLContext buildSSLContext() {
try {
return SSLContextBuilder.create()
.loadTrustMaterial((chain, authType) -> true) // 信任所有证书
.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
同时需要配置禁用主机名验证(可选):
.withHostnameVerifier(NoopHostnameVerifier.INSTANCE)
4. 使用环境变量或启动参数(临时绕过)
在 JVM 启动时添加:
-Djavax.net.ssl.trustStore=/path/to/mytruststore.jks \
-Djavax.net.ssl.trustStorePassword=mypassword
总结
| 方案 | 适用场景 | 安全性 |
|---|---|---|
| 导入 JVM 信任库 | 开发/测试环境,固定机器 | 中等,需管理证书 |
| 自定义 TrustStore | 可移植,分环境配置 | 中等 |
| 禁用 SSL 验证 | 仅开发调试,快速验证 | 极低,禁止用于生产 |
| JVM 启动参数 | 容器或脚本启动时统一设置 | 中等 |
建议在开发环境使用方案 1 或 2,生产环境务必使用正式的 CA 签发证书并正确配置信任链。