微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将数据从 Java 发送到 Elastic Cloud?

如何解决如何将数据从 Java 发送到 Elastic Cloud?

我想在 Java 应用程序的 Elastic Cloud 中运行的 Elastic Search 中插入(索引)一些数据。

为此,我编写了以下代码

void sendStuffToElasticSearch() {
    RestHighLevelClient client = null;
    try {
        client = new RestHighLevelClient(
                RestClient.builder(CLOUD_ID)
        );

        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
        builder.addHeader("Authorization",String.format("ApiKey %s",API_KEY));
        final RequestOptions requestOptions = builder.build();

        IndexRequest request = new IndexRequest("posts");
        request.id("1");
        String jsonString = "{" +
                "\"user\":\"kimchy\"," +
                "\"postDate\":\"2013-01-30\"," +
                "\"message\":\"trying out Elasticsearch\"" +
                "}";
        request.source(jsonString,XContentType.JSON);
        IndexResponse indexResponse = client.index(request,requestOptions);
        System.out.println("indexResponse");
    } catch (IOException e) {
        e.printstacktrace();
    } finally {
        IoUtils.closeQuietly(client);
    }
}

API_KEY 是我根据 this tutorial 生成的密钥,它还表示我需要以以下格式将其发送到 Authorization 标头中:Authorization: ApiKey $EC_API_KEY

当我运行上述代码时,出现以下错误

org.elasticsearch.client.ResponseException: method [PUT],host [https://XXXXXXXXXX:9243],URI [/posts/_doc/1?timeout=1m],status line [HTTP/1.1 401 Unauthorized]
{"error":{"root_cause":[{"type":"security_exception","reason":"missing authentication credentials for REST request [/posts/_doc/1?timeout=1m]","header":{"WWW-Authenticate":["Basic realm=\"security\" charset=\"UTF-8\"","Bearer realm=\"security\"","ApiKey"]}}],"type":"security_exception","ApiKey"]}},"status":401}
        at org.elasticsearch.client.RestClient.convertResponse(RestClient.java:326)
        at org.elasticsearch.client.RestClient.performRequest(RestClient.java:296)
        at org.elasticsearch.client.RestClient.performRequest(RestClient.java:270)
        at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1621)
        ... 30 more

如何解决这个问题,我。 e.以 Elastic Cloud 期望的方式提供所有与身份验证相关的数据?

我正在使用以下库:

    <properties>
        [...]
        <elastic-search-client.version>7.11.1</elastic-search-client.version>
    </properties>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>${elastic-search-client.version}</version>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>${elastic-search-client.version}</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>${elastic-search-client.version}</version>
        </dependency>

更新 1: API 密钥的 Base64 编码建议 here(见下面的代码)没有帮助。

            RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
            builder.addHeader("Authorization",Base64.getEncoder().encodetoString(API_KEY.getBytes(StandardCharsets.UTF_8))));
            final RequestOptions requestOptions = builder.build();

更新 2: 更改我创建客户端的方式也无济于事(见下文)。

            Header[] defaultHeaders =
                    new Header[]{new BasicHeader("Authorization",API_KEY))};
            final RestClientBuilder builder1 = RestClient.builder(CLOUD_ID);
            builder1.setDefaultHeaders(defaultHeaders);
            client = new RestHighLevelClient(
                    builder1
            );

更新 3:我将提供的 API 密钥更改为

public static final String BASE64_API_KEY = Base64.getEncoder().encodetoString(String.format("%s:%s",ID,KEY).getBytes());

正如里卡多·费雷拉所建议的那样。

现在我收到一个不同的错误

org.elasticsearch.client.ResponseException: method [PUT],host [XXXXXXXXXXXXXXXX],status line [HTTP/1.1 403 Forbidden]
{"error":{"root_cause":[{"type":"security_exception","reason":"action [indices:admin/auto_create] is unauthorized for API key id [XXXXXXXXXXXXXXXX] of user [XXXXXXXXXXXXXXXX]"}],"reason":"action [indices:admin/auto_create] is unauthorized for API key id [XXXXXXXXXXXXXXXX] of user [XXXXXXXXXXXXXXXX]"},"status":403}
        at org.elasticsearch.client.RestClient.convertResponse(RestClient.java:326)
        at org.elasticsearch.client.RestClient.performRequest(RestClient.java:296)
        at org.elasticsearch.client.RestClient.performRequest(RestClient.java:270)
        at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1621)
        ... 30 more

更新 4:

在我创建了有问题的索引后,错误信息变成了这样:

org.elasticsearch.client.ResponseException: method [PUT],URI [/camunda-1/_doc/1?timeout=1m],"reason":"action [indices:data/write/bulk[s]] is unauthorized for API key id [XXXXXXXXXXXXXXXX] of user [XXXXXXXXXXXXXXXX]"}],"reason":"action [indices:data/write/bulk[s]] is unauthorized for API key id [XXXXXXXXXXXXXXXX] of user [XXXXXXXXXXXXXXXX]"},"status":403}

解决方法

它不起作用,因为您使用了错误的 API 密钥。 ?

不过别担心:这些事情经常发生。这当然发生在我身上。

您正在创建的 API 密钥用于向 Elasticsearch Service 发出 REST 请求,Elasticsearch Service 是管理您的 Elasticsearch 和 Kibana 集群的实体。

要使其工作,您需要专门从 Elasticsearch 创建一个 API 密钥。要创建一个,请转到 Dev Tools Console 并发出以下请求:

POST _security/api_key
{
   "name": "my-api-key","expiration": "7d","role_descriptors": {
      "custom-role": {
         "cluster": ["all"],"index": [
            {
               "names": [
                  "index-1","index-2"
               ],"privileges": ["all"]
            }
         ]
      }
   }
}

如果执行成功,你会得到这样的响应:

{
  "id" : "liKs_XcBrNsSAgwboCN9","name" : "my-api-key","expiration" : 1615473484899,"api_key" : "NC3ZeIb_SGWjGJRZVoOf2g"
}

注意字段 idapi_key。您将需要它们来创建授权标头:

String apiKey = String.format("%s:%s",id,api_key);
apiKey = Base64.getEncoder().encodeToString(apiKey.getBytes());
String authorization = String.format("ApiKey %s",apiKey);

在此之后只需在您的 Java 代码中使用授权:

builder.addHeader("Authorization",authorization);

玩得开心?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?