ElasticSearch 8.x 使用 High Level Client 以 HTTPS 方式链接,SSL 证书、主机名验证器 各是什么,如何忽略

ElasticSearch

1、ElasticSearch学习随笔之基础介绍

2、ElasticSearch学习随笔之简单操作

3、ElasticSearch学习随笔之java api 操作

4、ElasticSearch学习随笔之SpringBoot Starter 操作

5、ElasticSearch学习随笔之嵌套操作

6、ElasticSearch学习随笔之分词算法

7、ElasticSearch学习随笔之高级检索

8、ELK技术栈介绍

9、Logstash部署与使用

10、ElasticSearch 7.x 版本使用 BulkProcessor 实现批量添加数据

11、ElasticSearch 8.x 弃用了 High Level REST Client,移除了 Java Transport Client,推荐使用 Elasticsearch Java API

12、ElasticSearch 8.x 使用 snapshot(快照)进行数据迁移

13、ElasticSearch 8.x 版本如何使用 SearchRequestBuilder 检索

14、ElasticSearch 8.x 使用 High Level Client 以 HTTPS 方式链接,SSL 证书、主机名验证器 各是什么,如何忽略

ElasticSearch,创始人 Shay Banon(谢巴农)

本文主要讲解ElasticSearch 高级搜索实战,来满足复杂的业务场景,还是用 Kibana 来操作。


文章目录


前言

在平时测试环境中,我们可以通过 IP 地址 或者 域名【http://***】来简单粗暴的连接 ElasticSearch 服务,比较内网测试没必要考虑别的,连接上能进行索引的操作即可;不过到了生产环境,安全问题成了 头号杀手 ,毕竟数据无价嚒,不过目前很多企业应用都会部署到云端,应用ElasticSearch 服务之前其实也是属于内网连接,并不会暴漏链接到外面,再加上云服务自身的安全和防火前的保护,所以安全基本上不用考虑了。

可以公司是有规范的,无论是 DB 数据库还是缓存,还是像 ElasticSearch 这种搜索引擎必须要有 用户名和密码 这层安全校验的,这是安全最基本的,所以应对不同的环境 或许 就需要不同的连接方式了。

一:pom 依赖

对于 ElasticSearch 客户端的版本,不需要太高,稳定很重要,对于有些莫名其妙的问题,换一个 版本的 客户端有可能就好了,亲身经历

java 复制代码
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.15.2</version>
</dependency>

二:开放式连接方式

三:用户名密码验证方式

这种方式在其他博客中已经提到好几次了,放到这里只为有需要的 码友 们拷贝代码。

java 复制代码
private static RestHighLevelClient createClient(){
    String hostname = "192.168.0.67";
    int port = 9200;
    String esUsername = "your es username";
    String esPassword = "your es password";
    final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(esUsername, esPassword));
    RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(hostname, port))
            .setHttpClientConfigCallback(httpAsyncClientBuilder -> httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
    return new RestHighLevelClient(restClientBuilder);
}

四:忽略 SSL证书 和 主机名验证

生产环境的 ElasticSearch 有时可能是通过域名来访问的,并且是 https 开头的,那就需要 SSL/TLS 认证了,但是我们并不需要,那只能忽略了。

4.1 忽略 SSL 认证

按上面说的,ElasticSearch 访问地址是 https://***,而只配置了 用户名密码,那用客户端链接则 可能 会报如下错误:

bash 复制代码
javax.net.ssl.SSLHandshakeException:PKIX path building failed:sun.security.provider.certpath.SunCertPathBuilderException:unable to find valid certification path to requested target
at org.elasticsearch.client.RestClient.extractAndWrapCause(RestClient.java:783)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:218)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:205)
at org.elasticsearch.client.RestHighLevelclient.internalPerformRequest(RestHighLevelclient.java:1454)
at org.elasticsearch.client.RestHighLevelclient.performRequest(RestHighLevelclient.java:1424)

此时我们需要忽略 SSL 认证,然忽略 SSL 的写法也有好几种。

注意: 以下三种方式选择其中一种就可以,那种适合就用那种。

方式一

首先获取 TLS 的 SSLContext 实例,再进行初始化,初始化的时候什么都不做。

java 复制代码
public static RestHighLevelClient createClient(){
    String hostname = "es.test.com";
    int port = 9200;
    String esUsername = "your es username";
    String esPassword = "your es password";
    // 配置用户名和密码
    CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(esUsername, esPassword));
    RestClientBuilder clientBuilder = RestClient.builder(new HttpHost(hostname, port, "https"));
    clientBuilder.setHttpClientConfigCallback( httpAsyncClientBuilder -> {
                // 配置认证支持
                httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                // 忽略证书配置
                try {
                    SSLContext sslContext = SSLContext.getInstance("TLS");
                    sslContext.init(null, new TrustManager[] {
                                    new X509TrustManager() {
                                        @Override
                                        public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
                                                throws CertificateException {
                                            // 忽略证书错误 信任任何客户端证书
                                        }

                                        @Override
                                        public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
                                                throws CertificateException {
                                            // 忽略证书错误 信任任何客户端证书
                                        }

                                        @Override
                                        public X509Certificate[] getAcceptedIssuers() {
                                            return new X509Certificate[0];
                                        }
                                    }
                            },
                            null);
                    httpAsyncClientBuilder.setSSLContext(sslContext);
                } catch (NoSuchAlgorithmException | KeyManagementException e) {
                    System.out.println("忽略证书错误");
                }
                // 忽略 hostname 校验认证
                httpAsyncClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
                return httpAsyncClientBuilder;
            });
    return new RestHighLevelClient(clientBuilder);
}

方式二

首先创建一个信任策略的 TrustStrategy,再通过策略构建一个 SSLContext 。

java 复制代码
public static RestHighLevelClient createClient(){
    String hostname = "es.test.com";
    int port = 9200;
    String esUsername = "your es username";
    String esPassword = "your es password";
    // 配置用户名和密码
    CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(esUsername, esPassword));
    RestClientBuilder clientBuilder = RestClient.builder(new HttpHost(hostname, port, "https"));
    clientBuilder.setHttpClientConfigCallback(httpAsyncClientBuilder -> {
        httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
        try {
            // 创建一个信任所有证书的 TrustStrategy 策略
            TrustStrategy acceptTrustStrategy = (chain, authType) -> true;
            // 使用 SSLContextBuilder 创建 SSLContext
            SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial(null, acceptTrustStrategy).build();
            httpAsyncClientBuilder.setSSLContext(sslContext);
        } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
            e.printStackTrace();
        }
        return httpAsyncClientBuilder;
    });
    return new RestHighLevelClient(clientBuilder);
}

方式三

这里需要一个引入一个第三方的 jar 包,封装了我们需要的 SSL 认证实例。

java 复制代码
<dependency>
    <groupId>io.github.hakky54</groupId>
    <artifactId>sslcontext-kickstart</artifactId>
    <version>8.1.4</version>
</dependency>

下面通过第三方 jar 包提供的 SSLFactory 来得到 SSLContext 。

java 复制代码
public static RestHighLevelClient createClient(){
    String hostname = "es.test.com";
    int port = 9200;
    String esUsername = "your es username";
    String esPassword = "your es password";
    // 用户名和密码认证
    CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(esUsername, esPassword));
    // 配置策略工厂
    SSLFactory sslFactory = SSLFactory.builder()
            .withUnsafeTrustMaterial()
            .withUnsafeHostnameVerifier()
            .build();
    RestClientBuilder clientBuilder = RestClient.builder(new HttpHost(hostname, port, "https"));
    clientBuilder.setHttpClientConfigCallback(httpAsyncClientBuilder -> {
        httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
        // 通过策略工厂获取一个 SSLContext
        httpAsyncClientBuilder.setSSLContext(sslFactory.getSslContext());
        return httpAsyncClientBuilder;
    });
    return new RestHighLevelClient(clientBuilder);
}

4.2 忽略 主机名验证

处理 SSL 认证,还有可能包如下错误:

bash 复制代码
java.io.IOException: Host name 'devintes.jibo.cn' does not match the certificate subject provided by the peer (CN=elasticsearch-devint-master)

我们接着忽略,只需要在忽略 SSL 是再忽略 主机名验证就可以了,代码如下:

java 复制代码
httpAsyncClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);

其实再上面的 方式三 中,用 SSLFactory 也是可以忽略的。

相关推荐
xlsw_1 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹2 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭2 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫3 小时前
泛型(2)
java
超爱吃士力架3 小时前
邀请逻辑
java·linux·后端
南宫生3 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石3 小时前
12/21java基础
java
李小白663 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp3 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
woshiabc1113 小时前
windows安装Elasticsearch及增删改查操作
大数据·elasticsearch·搜索引擎