1. 程式人生 > >ElasticSearch-Java-SearchGuard連線和使用

ElasticSearch-Java-SearchGuard連線和使用

Elasticsearch

主要是Elasticsearch使用searchguard後Java連線及安全驗證

安全驗證這部分大多選擇的Xpack,但Xpack收費當時就用了searchguard,但searchguard相關的文件很少,算是一點點去看官方文件解決。

1. searchGuard與ELK的結合

1.1 安全證書可以通過官方網站線上生成,填寫叢集節點資訊。郵件傳送後下載到本地。
1.2 金鑰證書生成後必須將DN配置到elasticsearch.yml中。

在這裡插入圖片描述

證書生成方式不同DN不同,要檢視DN確保正確(命令可百度檢視證書DN)。同時search guard配置檔案中要加入該DN賬戶給該DN以賬戶和許可權。

sg_internal_users.yml:

在這裡插入圖片描述

sg_roles_mapping.yml

在這裡插入圖片描述

3. 這裡兩個較好的部落格
https://www.jianshu.com/p/91faac8e18cf
https://blog.csdn.net/z1x2c34/article/details/77968955#commentBox
4. 證書檔案在ops/resource中
  • CN=sgadmin-keystore.jks和truststore.jks。
  • clientUtil類在/service/util註冊成bean.
5. 一些具體的es和安全外掛的api建議去官網看,較詳細。
6. 我會貼出我的相關配置檔案以及部分程式碼供以參考.

2. searchGuard與Java的結合-建立client

2.1. 當es安裝searchGuard後就不能直接建立client連線了
2.2. 首先需要把 truststore.jks和CN=sgadmin-keystore.jks放到專案中,建立連線時需讀取進行安全驗證(不通過賬戶密碼)
2.3. 其次在需要指定連線引數
 Settings settings = Settings.builder()
                    .put("searchguard.ssl.transport.enabled", true)
                    .put("searchguard.ssl.transport.keystore_filepath",xxx)
                    .put("searchguard.ssl.transport.truststore_filepath",xxx)
                    .put("searchguard.ssl.transport.keystore_password", "xxx")
                    .put("searchguard.ssl.transport.truststore_password", "xxx")
                    .put("searchguard.ssl.http.keystore_password", "xxx")
                    .put("searchguard.ssl.http.truststore_password", "xxx")
                    .put("searchguard.ssl.transport.enforce_hostname_verification", false)
                    .put("client.transport.ignore_cluster_name", true)
                    .build();
這裡的password需要注意,具體值在你生成安全證書檔案中的ReadMe.md中。
在:
Common passwords                                                                            
Truststore password:  xxx                       
Admin keystore and private key password:  xxx

3.匯入資料

3.1支援json格式匯入,我這裡是將Bean轉成json格式匯入
         ObjectMapper mapper = new ObjectMapper();
            try {
                mapJackson = mapper.writeValueAsString(xcBean);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
3.2匯入時如果資料量較大,可以使用BulkRequestBuilder批量匯入
			//指定index和type
			BulkRequestBuilder bulkRequest = esClient.prepareBulk();
            bulkRequest.add(esClient.prepareIndex("xingce", "xc").setSource(mapJackson, XContentType.JSON));
            if (count % 500 == 0) {
                bulkRequest.execute().actionGet();
                //此處新建一個bulkRequest,類似於重置效果。避免重複提交
                bulkRequest = esClient.prepareBulk();
            }

4. 搜尋

4.1 具體搜尋API不再列出,百度即可,我使用的是bool+should
/**
     * 拼接查詢條件
     **/
    public QueryBuilder getQb(EsPageRequestBean esPageRequestBean) {
        //多條件設定
        MatchQueryBuilder mpq1 = QueryBuilders
                .matchQuery(ES_TITLE, esPageRequestBean.getQuery());
        MatchQueryBuilder mpq2 = QueryBuilders
                .matchQuery(ES_QUESTIONS, esPageRequestBean.getQuery());
        MatchQueryBuilder mpq3 = QueryBuilders
                .matchQuery(ES_MATERIALS, esPageRequestBean.getQuery());
        QueryBuilder qb = QueryBuilders.boolQuery()
                .should(mpq1)
                .should(mpq2)
                .should(mpq3);
        return qb;
    }
4.2 高亮顯示
	/**
     * 拼接高亮查詢
     **/
    public HighlightBuilder getHb() {
        HighlightBuilder hiBuilder = new HighlightBuilder();
		//這裡設定包含高亮關鍵字的標籤
        hiBuilder.preTags("<mark>").postTags("</mark>");
		//這裡fields中設定需要高亮顯示的查詢欄位,名字是Es中的欄位名
        hiBuilder.field(ES_TITLE).field(ES_QUESTIONS).field(ES_MATERIALS);
        return hiBuilder;
    }
4.3 分頁
分頁有兩種,我這裡使用的from,size.不過第一次查詢獲取總數時建議不拿資料只取counts,.setSize(0):這樣提高速度也能避免浪費效能
	//查詢建立
        SearchRequestBuilder responseBuilder = esClient
                .prepareSearch("interview").setTypes("iv");

        //第一次查詢建立獲取總條數分頁使用
        SearchResponse myResponse = responseBuilder
                .setQuery(qb)
                .setSearchType(SearchType.QUERY_THEN_FETCH)
                .setSize(0)
                .setExplain(true).execute().actionGet();
        //獲取總數
        long counts = myResponse.getHits().totalHits;
4.4 建立查詢
    //根據分頁資訊查詢
        SearchResponse pageResponse = responseBuilder
                .setQuery(qb)
                .highlighter(hiBuilder)
                .setFrom((esRequestBean.getPage() - 1) * esRequestBean.getPageSize()).setSize(esRequestBean.getPageSize())
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setExplain(true).execute().actionGet();
        SearchHits pageHits = pageResponse.getHits();
        //迴圈裝配bean
        for (SearchHit searchHit : pageHits) {
            Map source = searchHit.getSource();
            HighlightField titleHighlight = searchHit.getHighlightFields().get(ES_TITLE);
            HighlightField questionHighlight = searchHit.getHighlightFields().get(ES_QUESTIONS);
            HighlightField materialsHighlight = searchHit.getHighlightFields().get(ES_MATERIALS);
			//這裡將取出的json資料轉成bean再處理
            YourBean yourBean = (YourBean) JSONObject.toBean(JSONObject.fromObject(source), YourBean.class, classMap);
			.....
			.....
			}

4.4.1這裡的classMap注意,當某欄位資訊是巢狀型別時 需要設好接受該欄位的Map資訊
	//對於巢狀陣列型別,從Es中讀取時需先反射定義好map
        Map<String, Class> classMap = new HashMap<String, Class>();
        classMap.put("es中欄位", 接收該欄位Bean.class);
       

5.原始碼

具體相關程式碼於本人GitHub:https://github.com/liyifan687/Elasticsearch