【问题标题】:How to connect 'spring boot 2.1 with elasticsearch 6.6' with cluster node 'https'?如何将“spring boot 2.1 with elasticsearch 6.6”与集群节点“https”连接起来?
【发布时间】:2019-12-31 19:13:29
【问题描述】:

我正在开发一个涉及模糊搜索的新项目,因此我正在使用 spring boot (v2.1.5) 开发 elasticsearch (v6.4.3)。我无法在 spring boot 和 elasticsearch 之间建立连接,因为我必须将用户名、密码、ca_certificate_base64 从 spring boot 传递到 elasticsearch 才能建立连接。您能否让我知道如何建立连接以及什么弹性搜索客户端是正确的选项?示例或链接会有所帮助。

在本地(我的笔记本电脑),我确实安装了 elasticsearch 6 和 spring boot 2.1.5。我能够建立连接(使用弹簧数据),因为不需要“https”连接或传递用户名和密码,因为互联网上的大多数示例都在谈论 localhost:9200。

   public Client client() {
     Settings elasticsearchSettings = Settings.builder()
           .put("client.transport.sniff", true)
           .put("uri", "https://usertemp:ABCSAD@alp-usba-north-3-portal.11.db2lay.com:32117/")
           .put("uri_direct_1", "https://usertemp:ABCSAD@alp-usba-north-3-portal.11.db2lay.com:32117/")
           .put("cluster.name", clusterName).build();
      TransportClient client = new PreBuiltTransportClient(elasticsearchSettings);
}


I also tried to update application.properties file
'''
spring.data.elasticsearch.cluster-name=ee842f-93042
spring.data.elasticsearch.cluster-nodes=alp-usba-north-3-portal.11.db2lay.com:32117
spring.data.elasticsearch.properties.username=usertemp
spring.data.elasticsearch.properties.password=ABCSAD
spring.data.elasticsearch.properties.ca_certificate_base64=SUZJQ0FURS0tLS0tCk1JSURvekNDQW91Z0F3SUJBZ0lFWFA5Sjl6QU5CZ2

我期待与 spring boot 和 elasticsearch 的联系。但是,当我启动应用程序服务器时出现以下错误。

引起:org.springframework.beans.BeanInstantiationException:无法实例化[org.elasticsearch.client.transport.TransportClient]:工厂方法'elasticsearchClient'抛出异常;嵌套异常是 java.lang.IllegalArgumentException: unknown setting [password] 请检查是否安装了任何必需的插件,或检查破坏性更改文档以获取已删除的设置 在 org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE] 在 org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE] ...省略了96个常用框架 引起:java.lang.IllegalArgumentException: unknown setting [password] 请检查是否安装了任何必需的插件,或检查破坏性更改文档以了解已删除的设置 在 org.elasticsearch.common.settings.AbstractScopedSettings.validate(AbstractScopedSettings.java:393) ~[elasticsearch-6.4.3.jar:6.4.3]

【问题讨论】:

  • 您配置的 TransportClient 使用原生协议(不是 HTTP/HTTP),并且通常在端口 9300 上运行。HTTP(S) 用于使用 REST 客户端访问集群时,通常使用端口 9200。因此请检查您是否使用了正确的客户端以及您的服务器是如何设置的。
  • @Meisch,谢谢,是的,我确实检查了云环境(compose for elasticsearch)服务,在那里我找到了凭证和证书信息。现在,我需要将 Spring Boot 应用程序中的凭据和证书传递给 elasticsearch 以获取连接和进一步通信。 您能否让我知道哪个客户端是正确的选择,因为我对 Spring Boot 数据和 Elasticsearch 都是新手? 他们提供了一个关于如何使用 Node JS 连接到弹性搜索的示例。 github.com/IBM-Cloud/compose-elasticsearch-helloworld-nodejs/…
  • 从未与 IBM Compse for Elastic 合作过,他们网站上的文档几乎不存在。查看 Javascript 示例,您似乎需要使用客户端证书来访问它,而不是用户/密码。我会尝试是否可以在本地设置类似的东西来测试如何连接
  • 顺便说一句,您使用哪个 ES 版本?您的问题主题提到 6.6,但在帖子中您谈论的是 6.4.3 - 并且一直在考虑用户/密码:您可能需要 ES 和连接证书
  • @Meisch,云上的 ES 版本是 6.6.2。在我的本地,我尝试使用 Spring boot 2.1.5 附带的 ES 6.4.3。提前致谢。

标签: java spring-boot elasticsearch spring-data-elasticsearch


【解决方案1】:

正如我在 cmets 中已经提到的,我不知道 IBM Compose for Elasticsearch 究竟是如何设置连接安全性的;我对这种情况的设置如下:

弹性搜索

  • Elasticsearch 6.6.2 在我的机器上运行
  • 在 Elasticsearch 前面作为代理运行的 NGINX
    • 基本身份验证已激活
    • 仅限 SSL
    • 需要 SSL 客户端证书

maven 和版本

为了能够通过 HTTPS 进行通信,您需要使用 RestClient,该 RestClient 在 Spring Data Elasticsearch 3.2 版中可用(目前在 3.2.0.M4 版中可用)。 Spring Boot 2.1.5 引入了 Spring Data Elasticsearch 3.1.8,因此您需要覆盖该版本。您还需要指定 Elasticsearch 版本以匹配 Spring Boot Data 3.2.0.M4,因此您的 pom.xml 需要以下条目:

<properties>
    <java.version>1.8</java.version>
    <elasticsearch.version>6.7.2</elasticsearch.version>
    <spring-data-elasticsearch>3.2.0.M4</spring-data-elasticsearch>
</properties>

<repositories>
    <repository>
        <id>spring-libs-snapshot</id>
        <name>Spring Snapshot Repository</name>
        <url>https://repo.spring.io/libs-milestones</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-elasticsearch</artifactId>
        <version>${spring-data-elasticsearch}</version>
    </dependency>
</dependencies>

Bean 配置

在您的程序中,您可以使用 AbstractElasticsearchConfiguration 的实现为 Spring Data Elasticsearch 配置 Bean:

@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {

    private static final Logger LOG = LoggerFactory.getLogger(RestClientConfig.class);

    private static final String CERT_FILE = "client.p12";
    private static final String CERT_PASSWORD = "topsecret";
    private static final String USER_NAME = "user";
    private static final String USER_PASS = "password";

    @Override
    public RestHighLevelClient elasticsearchClient() {

        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo("localhost:443")  // set the address of the Elasticsearch cluster
                .usingSsl(createSSLContext())  // use the SSLContext with the client cert
                .withBasicAuth(USER_NAME, USER_PASS)   // use the headers for authentication
                .build();

        return RestClients.create(clientConfiguration).rest();
    }

    private SSLContext createSSLContext() {
        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");

            KeyManager[] keyManagers = getKeyManagers();

            sslContext.init(keyManagers, null, null);

            return sslContext;
        } catch (Exception e) {
            LOG.error("cannot create SSLContext", e);
        }
        return null;
    }

    private KeyManager[] getKeyManagers()
            throws KeyStoreException, NoSuchAlgorithmException, IOException, CertificateException, UnrecoverableKeyException {
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(CERT_FILE)) {
            KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
            clientKeyStore.load(inputStream, CERT_PASSWORD.toCharArray());

            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(clientKeyStore, CERT_PASSWORD.toCharArray());
            return kmf.getKeyManagers();
        }
    }

    @Bean
    @Primary
    public ElasticsearchOperations elasticsearchTemplate() {
        return elasticsearchOperations();
    }
}

通过此设置,我可以使用 ElasticsearchRestTemplateElasticsearchRepository 针对 Elasticsearch 集群运行我的 Spring Boot 应用程序。

您可能需要调整 getKeyManagers() 方法中的代码以匹配您从 Compose 中获得的代码,但这应该为您提供一些起点。

【讨论】:

  • @Meisch,非常感谢。从云端,我没有获得证书文件,而是他们提供了可用作 Base64 编码数据的可信证书。所以,我确实编写了解码证书的代码,然后将其添加到密钥库中。但是,无法弄清楚将 sslcontext 传递给 ClientConfiguration.build()。在这里,由于允许的字符数,我可以输入代码 sn-p。
  • 在构建 SSLContext 之后,将其添加到 ClientConfiguration 构建器作为 usingSsl() 方法的参数,就像在我的示例中一样。
  • @Meisch,根据您的示例代码,我确实尝试实现 RestClientConfig 类,但是当我尝试使用 ElasticsearchRepository 时出现异常,因此删除了 ElasticsearchRepository 而是尝试 ping 集群 rhlc.ping(RequestOptions.DEFAULT)异常是 org.apache.http.ConnectionClosedException: Connection is closed [err] at org.elasticsearch.client.RestClient$SyncResponseListener.get(RestClient.java:942) 原因:org.apache.http.ConnectionClosedException: Connection is closed [错误] 在 org.apache.http.nio.protocol.HttpAsyncRequestExecutor.endOfInput(HttpAsyncRequestExecutor.java:356)
  • @Meisch,非常感谢您的帮助和指导。我确实尝试用谷歌搜索异常但没有得到太多帮助。我将正确的数据传递给 ClientConfiguration.builder().connectedTo(alp-usba-north-3-portal.11.db2lay.com:32117).usingSsl(sslcontext).withDefaultHeaders(header).build();现在,标头包含基本身份验证信息。问题可能是 sslContext。如果是,请告诉我任何解决根本原因的方法吗?
  • 下面的代码 sn-p 从 SslcontextConfig.init() 获取 sslContext 并在 .usingSsl() 方法private SSLContext createSSLContext() { try { SSLContext sslContext = null; ConfigurableBeanFactory configBeanFactory = sslcontectConfig.getConfigurableBeanFactory(); sslContext = (SSLContext) configBeanFactory.getBean("ca_certificate_base64"); return sslContext; } catch (Exception e) { LOG.error("cannot create SSLContext", e); } return null; } 调用我确实尝试用谷歌搜索异常但没有得到太多帮助。你能指导我哪里出错了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-29
  • 2022-10-31
  • 2020-12-28
  • 1970-01-01
  • 2018-10-11
  • 2019-05-23
  • 2021-09-15
相关资源
最近更新 更多