Elasticsearch Auditing(es的審計功能)

陳家寶發表於2020-10-06

在Spring Data Elasticsearch中,提供了審計功能。即資料的建立人、建立時間、最後修改人等等,都是可以記錄追蹤的。本文示例如何使用es的審計功能。

目錄

一、資料實體類實現Persistable介面

二、提供AuditorAware

三、啟用審計功能

四、測試


一、資料實體類實現Persistable介面

package cn.jack.elasticsearchdemo.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.elasticsearch.client.security.user.User;
import org.springframework.data.annotation.*;
import org.springframework.data.domain.Persistable;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.time.Instant;
import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "jack_person")
@TypeAlias("human")
public class Person implements Persistable<String> {
    @Id
    private String id;
    @Field(fielddata = true)
    private String name;
    private String gender;

    private Book book;
    private List<String> hobbies;

    @Transient
    private String abc;

    // ========= 審計需要的相關欄位 =========
    @Field(type = FieldType.Date, format = DateFormat.basic_date_time)
    @CreatedDate
    private Instant createdDate;
    @CreatedBy
    private User createdBy;
    @Field(type = FieldType.Date, format = DateFormat.basic_date_time)
    @LastModifiedDate
    private Instant lastModifiedDate;
    @LastModifiedBy
    private User lastModifiedBy;

    /**
     * to determine if an enitity is new in Elasticsearch
     * @return
     */
    @Override
    public boolean isNew() {
        return id == null
                || (createdDate == null && createdBy == null);
    }
}

二、提供AuditorAware

提供AuditorAware,讓審計模組知道當前是誰在操作。

package cn.jack.elasticsearchdemo.config;

import org.elasticsearch.client.security.user.User;
import org.springframework.data.domain.AuditorAware;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Optional;

@Component  // 交由spring管理,否則無法獲取使用者資訊
public class EsAuditorAware implements AuditorAware<User> {
    @Override
    public Optional<User> getCurrentAuditor() {
        // 模擬獲取當前使用者
        User user = new User("jack", Arrays.asList("ROLE_ADMIN"));

        return Optional.ofNullable(user);

        /**
         * 如果許可權模組使用的是Spring Security,可以使用以下程式碼獲取當前使用者
         */
        /*return Optional.ofNullable(SecurityContextHolder.getContext())
                .map(SecurityContext::getAuthentication)
                .filter(Authentication::isAuthenticated)
                .map(Authentication::getPrincipal)
                .map(User.class::cast);*/
    }
}

三、啟用審計功能

在java config配置類,或者application主類上,通過@EnableElasticsearchAuditing註解啟用審計功能。

package cn.jack.elasticsearchdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
import org.springframework.data.elasticsearch.client.reactive.ReactiveRestClients;
import org.springframework.data.elasticsearch.config.EnableElasticsearchAuditing;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import org.springframework.http.HttpHeaders;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)		// 專案沒有用到關係型資料庫,排除此類,避免啟動異常
@EnableElasticsearchRepositories(basePackages = "cn.jack.elasticsearchdemo.repository")	// dao所在包名,不加此配置則需要每個dao都加上@Repository註解交由spring管理
@EnableElasticsearchAuditing	// 啟用審計功能
public class ElasticsearchdemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(ElasticsearchdemoApplication.class, args);
	}
}

四、測試

使用junit進行單元測試。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ElasticsearchdemoApplication.class)
@Slf4j
public class EsTest {
    @Autowired
    private PersonRepository personRepository;

    @Test
    public void testAuditing() {
        Person person = new Person();
        person.setName("審計測試5");
        this.personRepository.save(person);
        System.out.println(person);

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        person.setHobbies(Arrays.asList("跳舞"));
        this.personRepository.save(person);
        System.out.println(person);
    }
}

通過控制檯輸出可以確定,審計功能生效。

Person(id=Ozxk_XQBrwRoe5ExL8Fn, name=審計測試5, gender=null, book=null, hobbies=null, abc=null, createdDate=2020-10-06T10:10:35.418001600Z, createdBy=User[username=jack,roles=[ROLE_ADMIN],metadata={},fullName=null,email=null], lastModifiedDate=2020-10-06T10:10:35.418001600Z, lastModifiedBy=User[username=jack,roles=[ROLE_ADMIN],metadata={},fullName=null,email=null])
Person(id=Ozxk_XQBrwRoe5ExL8Fn, name=審計測試5, gender=null, book=null, hobbies=[跳舞], abc=null, createdDate=2020-10-06T10:10:35.418001600Z, createdBy=User[username=jack,roles=[ROLE_ADMIN],metadata={},fullName=null,email=null], lastModifiedDate=2020-10-06T10:10:36.617001600Z, lastModifiedBy=User[username=jack,roles=[ROLE_ADMIN],metadata={},fullName=null,email=null])

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相關文章