Java 连接 Elasticsearch 8.x 安全模式:证书校验与 ApiKey 认证
Elasticsearch 8.x 默认开启安全特性,强制 HTTPS 和身份认证。 Java 客户端如何加载自签名 CA 证书构建 TrustStore,配置 SSLContext 以解决握手失败问题。同时演示如何使用 ApiKey 进行身份验证,替代明文密码。涵盖依赖配置、Spring Boot 组件实现、主机名验证风险及常见问题排查,帮助开发者安全连接 ES 集群。

Elasticsearch 8.x 默认开启安全特性,强制 HTTPS 和身份认证。 Java 客户端如何加载自签名 CA 证书构建 TrustStore,配置 SSLContext 以解决握手失败问题。同时演示如何使用 ApiKey 进行身份验证,替代明文密码。涵盖依赖配置、Spring Boot 组件实现、主机名验证风险及常见问题排查,帮助开发者安全连接 ES 集群。

Elasticsearch 8.x 版本迎来了一个重大的安全变革:默认开启安全特性(Security Features)。这意味着,当你安装好 ES 8.x 后,不再像以往那样可以直接通过 http://localhost:9200 匿名访问。集群默认强制启用 HTTPS (TLS/SSL) 加密传输,并要求进行身份认证。
对于 Java 开发者而言,这带来了一个直接的挑战:如何在代码中正确处理自签名证书(CA Certificate)并完成认证?如果处理不当,你会频繁遇到 SSLHandshakeException: PKIX path validation failed 或 unable to find valid certification path to requested target 等错误。
本文将基于提供的代码实例,深入剖析 Elasticsearch 8.x Java Client 的安全连接机制,分享如何优雅地加载 CA 证书、配置 SSLContext 并结合 ApiKey 完成安全连接。
在 7.x 及更早版本中,我们通常使用 RestHighLevelClient,且很多时候在开发环境会直接禁用 SSL 验证。但在 8.x 中:
config/certs/http_ca.crt)。Java 默认的 TrustStore(信任库)并不信任这个自签名证书,因此握手会失败。co.elastic.clients:elasticsearch-java),它基于 Jackson 和新的传输层,配置方式与旧版有所不同。解决方案的核心思路:
我们需要手动将 ES 生成的 http_ca.crt 加载到 Java 的 TrustStore 中,构建一个信任该证书的 SSLContext,并将其注入到 HTTP 客户端中。同时,配合 ApiKey 或账号密码进行认证。
下面是一个标准的 Spring Boot 组件实现,展示了如何安全地连接 ES 8.x。
确保你的 pom.xml 中包含以下核心依赖(版本需与 ES 服务端匹配,例如 8.11.1):
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.5.2</version>
</dependency>
<!-- Jackson for JSON processing (通常已包含,但显式声明更安全) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
请将 ES 生成的 http_ca.crt 证书文件放入项目资源目录下的 certs/ 文件夹中,以便代码正常连接。
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContexts;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.stereotype.Component;
import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
@Component
public class ElasticClientApplication {
String serverUrl = "https://192.168.0.100:9200";
String apiKey = "WmdoVHJwd0I2NE50W........";
String caPath = "certs/http_ca.crt";
public ElasticsearchClient getEsClient() {
try {
InputStream caInput = Thread.currentThread().getContextClassLoader().getResourceAsStream(caPath);
// 2. 解析证书
CertificateFactory CertificateFactory.getInstance();
(X509Certificate) factory.generateCertificate(caInput);
caInput.close();
KeyStore.getInstance();
trustStore.load(, );
trustStore.setCertificateEntry(, caCert);
SSLContexts.custom()
.loadTrustMaterial(trustStore, )
.build();
RestClient.builder(HttpHost.create(serverUrl))
.setDefaultHeaders( .apache.http.Header[]{
(, + apiKey)
})
.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
.setSSLContext(sslContext)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE));
builder.build();
(restClient, ());
(transport);
} (Exception e) {
System.err.println();
e.printStackTrace();
(, e);
}
}
}
CertificateFactory & KeyStore)代码中最关键的部分在于手动构建 TrustStore。
cacerts 只信任公共 CA(如 DigiCert, Let's Encrypt)。ES 自签名的 CA 不在其中。KeyStore (pkcs12 类型),将读取到的 http_ca.crt 作为一个受信任的条目放进去。SSLContexts.custom().loadTrustMaterial(trustStore, null),告诉 JVM:'除了系统默认信任的证书外,请额外信任这个 trustStore 里的证书'。NoopHostnameVerifier 的风险代码中使用了 .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)。
localhost 或 node-1 的,而你通过 IP 192.168.0.189 访问,也不会报错。NoopHostnameVerifier,使用默认的严格验证。代码使用了 Authorization: ApiKey ... 头。
elastic 超级用户的明文密码更安全,也便于轮换。POST /_security/api_key 生成,或在命令行使用 elasticsearch-cli 生成。PKIX path building failed 或 unable to find valid certification pathcaPath 路径是否正确,文件是否真的存在于 resources/certs/ 下。trustStore.setCertificateEntry。HostnameVerifier 相关错误NoopHostnameVerifier.INSTANCE。elasticsearch.yml 或证书生成命令中指定 IP 地址作为 SAN。在 Kibana Dev Tools 中测试该 Key 是否有效:
GET /_security/_authenticate
Authorization: ApiKey <your_key>
Elasticsearch 8.x 的安全默认值虽然增加了初始连接的复杂度,但这极大地提升了数据的安全性。通过上述代码,我们实现了:
cacerts,应用内部独立管理信任关系,部署更灵活。在实际项目中,建议将 serverUrl, apiKey, caPath 等敏感信息提取到配置文件(如 application.yml)或环境变量中,避免硬编码在代码里,以符合安全合规要求。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online