最近作者做一个es的搜索,之前采用的是7.12.1,本来接口都已经基本上写好了,后面es要升级到8.7.0,一升级就连接不上es8.7.0了,后面才发现原来es8是默认采用了HTTPS协议,需要配置认证证书,这个问题搞了好久好久,最后终于搞成功了,在此写一篇博客记录一下。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>3.1.0version>
<relativePath/>
parent>
<groupId>com.tomgroupId>
<artifactId>elasticsearch-serverartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>elasticsearch-servername>
<description>elasticsearch-serverdescription>
<properties>
<java.version>17java.version>
<mybatis.version>2.2.0mybatis.version>
<hutool.version>5.7.16hutool.version>
<gson.version>2.8.6gson.version>
<guava.version>29.0-jreguava.version>
<druid.version>1.2.14druid.version>
<aspectj.version>1.9.4aspectj.version>
<retrofit.version>2.2.20retrofit.version>
<mybatis-plus.version>3.4.0mybatis-plus.version>
<commons-io.version>2.4commons-io.version>
<fastjson.version>1.2.73fastjson.version>
<springdoc.version>1.4.4springdoc.version>
<nimbus-jose-jwt.version>3.10nimbus-jose-jwt.version>
<javax-mail.version>1.4.7javax-mail.version>
<jbcrypt.version>0.4jbcrypt.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-elasticsearchartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.github.xiaoymingroupId>
<artifactId>knife4j-spring-boot-starterartifactId>
<version>3.0.3version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-boot-starterartifactId>
<version>3.0.0version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>${fastjson.version}version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
plugins>
build>
project>
server:
port: 10086
servlet:
context-path: /elasticsearch
spring:
elasticsearch:
rest:
enable: true
uris: 127.0.0.1:9200
host: 127.0.0.1
port: 9200
username: elastic
password: xxxxxxx
index: indexName
crtName: http_ca.crt
logging:
level:
root: debug
如何获取这个http_ca.crt证书文件呢,这个可以登录es访问地址,比如说https://127.0.0.1:9200,输入账号密码,就可以在浏览器上下载证书啦,下载之后需要将这个文件的名称修改为http_ca.crt并且放到resource目录下面
@Configuration
@Slf4j
public class ElasticSearchConfig {
@Value("${spring.elasticsearch.rest.host}")
private String host;
@Value("${spring.elasticsearch.rest.enable}")
private boolean enable;
@Value("${spring.elasticsearch.rest.port}")
private int port;
@Value("${spring.elasticsearch.rest.username}")
private String userName;
@Value("${spring.elasticsearch.rest.password}")
private String passWord;
@Value("${spring.elasticsearch.rest.crtName}")
private String tempCrtName;
private static String crtName;
@PostConstruct
private void init() {
crtName = tempCrtName;
}
/**
* 解析配置的字符串,转为HttpHost对象数组
*
* @return
*/
private HttpHost toHttpHost() {
HttpHost httpHost = new HttpHost(host, port, "https");
return httpHost;
}
@Bean
public ElasticsearchClient clientByPasswd() throws Exception {
ElasticsearchTransport transport = getElasticsearchTransport(userName, passWord, toHttpHost());
return new ElasticsearchClient(transport);
}
private static SSLContext buildSSLContext() {
ClassPathResource resource = new ClassPathResource(crtName);
SSLContext sslContext = null;
try {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
Certificate trustedCa;
try (InputStream is = resource.getInputStream()) {
trustedCa = factory.generateCertificate(is);
}
KeyStore trustStore = KeyStore.getInstance("pkcs12");
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", trustedCa);
SSLContextBuilder sslContextBuilder = SSLContexts.custom()
.loadTrustMaterial(trustStore, null);
sslContext = sslContextBuilder.build();
} catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException |
KeyManagementException e) {
log.error("ES连接认证失败", e);
}
return sslContext;
}
private static ElasticsearchTransport getElasticsearchTransport(String username, String passwd, HttpHost... hosts) {
// 账号密码的配置
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, passwd));
// 自签证书的设置,并且还包含了账号密码
RestClientBuilder.HttpClientConfigCallback callback = httpAsyncClientBuilder -> httpAsyncClientBuilder
.setSSLContext(buildSSLContext())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.setDefaultCredentialsProvider(credentialsProvider);
// 用builder创建RestClient对象
RestClient client = RestClient
.builder(hosts)
.setHttpClientConfigCallback(callback)
.build();
return new RestClientTransport(client, new JacksonJsonpMapper());
}
}