在我之前的教程 “Elasticsearch:使用最新的 Elasticsearch Java client 8.0 来创建索引并搜索”,我详述了如何使用 Java client 8.0 来连接一个 Elasticsearch 8.x 的集群。在那个例子中,我们的 Elasticsearch 集群是不带有 HTTPS 的安全设置的。在 Elasticsearch 8.x 的安装中,HTTPS 的配置是默认的,而且它的证书是自签名的。我们该如何修改我们的 Java 客户端代码来进行含有证书的连接呢?
如果你还没有安装好自己的 Elasticsearch 集群,你可以参考我之前的文章 “如何在 Linux,MacOS 及 Windows 上进行安装 Elasticsearch” 来进行安装。
在接下来的示例中,我将使用 Elasticsearch 8.1.1 来进行展示。为了大家更好地理解我下面的代码,我把代码放到 github 上。你可以通过如下的命令来进行下载:
git clone https://github.com/liu-xiao-guo/elasticsearchjava-search8-https
在这篇文章中,我着重来讲一下和 Elasticsearch 的连接部分。其它的展示和之前的文章 “Elasticsearch:使用最新的 Elasticsearch Java client 8.0 来创建索引并搜索” 类似。
使用 Elasticsearch Java client 8.0 来连接带有 HTTPS 的集群
使用 Elasticsearch Java client 8.0 来连接带有 HTTPS 的集群_哔哩哔哩_bilibili
我们可以使用自己账号的用户名及密码来进行连接。在我们的展示中,我使用超级用户 elastic 来进行展示:
private static synchronized void makeConnection_https() throws CertificateException, IOException,
NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
final CredentialsProvider credentialsProvider =
new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("elastic", "FW5S2hBXhCNZDZ7BX9O-"));
Path caCertificatePath = Paths.get("/Users/liuxg/test/elasticsearch-8.1.2/config/certs/http_ca.crt");
CertificateFactory factory =
CertificateFactory.getInstance("X.509");
Certificate trustedCa;
try (InputStream is = Files.newInputStream(caCertificatePath)) {
trustedCa = factory.generateCertificate(is);
}
KeyStore trustStore = KeyStore.getInstance("pkcs12");
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", trustedCa);
SSLContextBuilder sslContextBuilder = SSLContexts.custom()
.loadTrustMaterial(trustStore, null);
final SSLContext sslContext = sslContextBuilder.build();
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "https"))
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(
HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setSSLContext(sslContext)
.setDefaultCredentialsProvider(credentialsProvider);
}
});
RestClient restClient = builder.build();
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
client = new ElasticsearchClient(transport);
asyncClient = new ElasticsearchAsyncClient(transport);
}
如上所示,我们需要修改账号 elastic 的密码以及证书的路径。一旦 client 及 asyncClient 被创建,那么我们就可以使用它们来进行操作。
我们创建如下的 makeConnection_token() 方法来进行连接:
private static synchronized void makeConnection_token() throws CertificateException, IOException,
NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
Path caCertificatePath = Paths.get("/Users/liuxg/test/elasticsearch-8.1.2/config/certs/http_ca.crt");
CertificateFactory factory =
CertificateFactory.getInstance("X.509");
Certificate trustedCa;
try (InputStream is = Files.newInputStream(caCertificatePath)) {
trustedCa = factory.generateCertificate(is);
}
KeyStore trustStore = KeyStore.getInstance("pkcs12");
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", trustedCa);
SSLContextBuilder sslContextBuilder = SSLContexts.custom()
.loadTrustMaterial(trustStore, null);
final SSLContext sslContext = sslContextBuilder.build();
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "https"))
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(
HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setSSLContext(sslContext);
}
});
// String apiKeyId = "SY6uOoABwRrDJxOdlx78";
// String apiKeySecret = "E8Ae8-FgScqT-nXCSBN0ew";
// String apiKeyAuth =
// Base64.getEncoder().encodeToString(
// (apiKeyId + ":" + apiKeySecret)
// .getBytes(StandardCharsets.UTF_8));
// Header[] defaultHeaders =
// new Header[]{new BasicHeader("Authorization",
// "ApiKey " + apiKeyAuth)};
// builder.setDefaultHeaders(defaultHeaders);
Header[] defaultHeaders =
new Header[]{new BasicHeader("Authorization",
"ApiKey U1k2dU9vQUJ3UnJESnhPZGx4Nzg6RThBZTgtRmdTY3FULW5YQ1NCTjBldw==")};
builder.setDefaultHeaders(defaultHeaders);
RestClient restClient = builder.build();
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
client = new ElasticsearchClient(transport);
asyncClient = new ElasticsearchAsyncClient(transport);
}
有关如何创建这个 API key,你可以参阅我之前的文章 “Elasticsearch:创建 API key 接口访问 Elasticsearch”。如果你不想手动来创建,那么你可以使用如下的 Kibana UI 来创建:
其它的操作和之前的文章介绍的是一样的。这里就不再累述了。
参考:
【1】Other authentication methods | Elasticsearch Java API Client [8.1] | Elastic
【2】Encrypted communication | Elasticsearch Java API Client [8.1] | Elastic