这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
curl -X POST "https://localhost:9200/_security/api_key?pretty"
--cacert es01.crt
-u elastic:123456
-H 'Content-Type: application/json'
-d'
{
"name": "my-api-key-10d",
"expiration": "10d"
}
'
{
"id" : "eUV1V4EBucGIxpberGuJ",
"name" : "my-api-key-10d",
"expiration" : 1655893738633,
"api_key" : "YyhSTh9ETz2LKBk3-Iy2ew",
"encoded" : "ZVVWMVY0RUJ1Y0dJeHBiZXJHdUo6WXloU1RoOUVUejJMS0JrMy1JeTJldw=="
}
为了便于管理依赖库版本和源码,《java与es8实战》系列的所有代码都以子工程的形式存放在父工程elasticsearch-tutorials中
《java与es8实战之二:实战前的准备工作》一文说明了创建父工程的详细过程
在父工程elasticsearch-tutorials中新建名为crud-with-security的子工程,其pom.xml内容如下
elasticsearch-tutorials
com.bolingcavalry
1.0-SNAPSHOT
../pom.xml
4.0.0
com.bolingcavalry
crud-with-security
jar
crud-with-security
1.0-SNAPSHOT
https://github.com/zq2599
org.springframework.boot
spring-boot-dependencies
${springboot.version}
pom
import
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-configuration-processor
true
org.projectlombok
lombok
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
junit
junit
org.junit.jupiter
junit-jupiter-api
test
org.junit.jupiter
junit-jupiter-engine
test
co.elastic.clients
elasticsearch-java
com.fasterxml.jackson.core
jackson-databind
jakarta.json
jakarta.json-api
org.springframework.boot
spring-boot-starter-web
org.apache.maven.plugins
maven-surefire-plugin
3.0.0-M4
false
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
src/main/resources
**/*.*
elasticsearch:
username: elastic
passwd: 123456
apikey: ZVVWMVY0RUJ1Y0dJeHBiZXJHdUo6WXloU1RoOUVUejJMS0JrMy1JeTJldw==
# 多个IP逗号隔开
hosts: 127.0.0.1:9200
@SpringBootApplication
public class SecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityApplication.class, args);
}
}
接下来是全文的重点:通过Config类向Spring环境注册服务bean,这里有这两处要注意的地方
第一个要注意的地方:向Spring环境注册的服务bean一共有两个,它们都是ElasticsearchClient类型,一个基于账号密码认证,另一个基于apiKey认证
第二个要注意的地方:SpringBoot向es服务端发起的是https请求,这就要求在建立连接的时候使用正确的证书,也就是刚才咱们从容器中复制出来再放入application.yml所在目录的es01.crt文件,使用证书的操作发生在创建ElasticsearchTransport对象的时候,属于前面总结的套路步骤中的一步,如下图红框所示
package com.bolingcavalry.security.config;
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 lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.StringUtils;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
@ConfigurationProperties(prefix = "elasticsearch") //配置的前缀
@Configuration
@Slf4j
public class ClientConfig {
@Setter
private String hosts;
@Setter
private String username;
@Setter
private String passwd;
@Setter
private String apikey;
/**
* 解析配置的字符串,转为HttpHost对象数组
* @return
*/
private HttpHost[] toHttpHost() {
if (!StringUtils.hasLength(hosts)) {
throw new RuntimeException("invalid elasticsearch configuration");
}
String[] hostArray = hosts.split(",");
HttpHost[] httpHosts = new HttpHost[hostArray.length];
HttpHost httpHost;
for (int i = 0; i httpAsyncClientBuilder
.setSSLContext(buildSSLContext())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.setDefaultCredentialsProvider(credentialsProvider);
// 用builder创建RestClient对象
RestClient client = RestClient
.builder(hosts)
.setHttpClientConfigCallback(callback)
.build();
return new RestClientTransport(client, new JacksonJsonpMapper());
}
private static ElasticsearchTransport getElasticsearchTransport(String apiKey, HttpHost...hosts) {
// 将ApiKey放入header中
Header[] headers = new Header[] {new BasicHeader("Authorization", "ApiKey " + apiKey)};
// es自签证书的设置
HttpClientConfigCallback callback = httpAsyncClientBuilder -> httpAsyncClientBuilder
.setSSLContext(buildSSLContext())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
// 用builder创建RestClient对象
RestClient client = RestClient
.builder(hosts)
.setHttpClientConfigCallback(callback)
.setDefaultHeaders(headers)
.build();
return new RestClientTransport(client, new JacksonJsonpMapper());
}
@Bean
public ElasticsearchClient clientByApiKey() throws Exception {
ElasticsearchTransport transport = getElasticsearchTransport(apikey, toHttpHost());
return new ElasticsearchClient(transport);
}
}
既然两个ElasticsearchClient对象都已经注册到Spring环境,那么只要在业务类中注入就能用来操作es了
新建业务类ESService.java,如下,可见通过Resource注解选择了账号密码鉴权的ElasticsearchClient对象
package com.bolingcavalry.security.service;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
@Service
public class ESService {
@Resource(name="clientByPasswd")
private ElasticsearchClient elasticsearchClient;
public void addIndex(String name) throws IOException {
elasticsearchClient.indices().create(c -> c.index(name));
}
public boolean indexExists(String name) throws IOException {
return elasticsearchClient.indices().exists(b -> b.index(name)).value();
}
public void delIndex(String name) throws IOException {
elasticsearchClient.indices().delete(c -> c.index(name));
}
}
package com.bolingcavalry.security.service;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ESServiceTest {
@Autowired
ESService esService;
@Test
void addIndex() throws Exception {
String indexName = "test_index";
Assertions.assertFalse(esService.indexExists(indexName));
esService.addIndex(indexName);
Assertions.assertTrue(esService.indexExists(indexName));
esService.delIndex(indexName);
Assertions.assertFalse(esService.indexExists(indexName));
}
}
再来试试ApiKey鉴权操作es,修改ESService.java源码,改动如下图红框所示
为了检查创建的索引是否符合预期,注释掉单元测试类中删除索引的代码,如下图,如此一来,单元测试执行完成后,新增的索引还保留在es环境中
再执行一次单元测试,依旧符合预期
用eshead查看,可见索引创建成功
至此,SpringBoot操作带有安全检查的elasticsearch8的实战就完成了,在SpringData提供elasticsearch8操作的库之前,基于es官方原生client库的操作是常见的elasticsearch8访问方式,希望本文能给您一些参考
名称 | 链接 | 备注 |
---|---|---|
项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
参与评论
手机查看
返回顶部