審計

基礎知識

Spring Data 提供了強大的支援,可以透明地跟蹤誰建立或更改了實體以及更改發生的時間。要從此功能中受益,您必須為您的實體類配備審計元資料,元資料可以使用註解或透過實現介面來定義。此外,必須透過註解配置或 XML 配置啟用審計功能,以註冊所需的底層元件。請參閱特定儲存的章節瞭解配置示例。

只跟蹤建立和修改日期的應用程式不需要讓其實體實現 AuditorAware

基於註解的審計元資料

我們提供 @CreatedBy@LastModifiedBy 用於捕獲建立或修改實體的使用者,以及 @CreatedDate@LastModifiedDate 用於捕獲更改發生的時間。

一個審計實體
class Customer {

  @CreatedBy
  private User user;

  @CreatedDate
  private Instant createdDate;

  // … further properties omitted
}

如您所見,可以有選擇地應用註解,具體取決於您希望捕獲的資訊。指示捕獲更改發生時間的註解可以用於 JDK8 日期和時間型別、longLong 以及舊版 Java DateCalendar 型別的屬性上。

審計元資料不一定非要位於根級別實體中,也可以新增到嵌入式實體中(取決於實際使用的儲存),如下面的程式碼片段所示。

嵌入式實體中的審計元資料
class Customer {

  private AuditMetadata auditingMetadata;

  // … further properties omitted
}

class AuditMetadata {

  @CreatedBy
  private User user;

  @CreatedDate
  private Instant createdDate;

}

基於介面的審計元資料

如果您不想使用註解來定義審計元資料,可以使您的領域類實現 Auditable 介面。它公開了所有審計屬性的 setter 方法。

AuditorAware

如果您使用 @CreatedBy@LastModifiedBy,審計基礎架構需要以某種方式知道當前的 Principal。為此,我們提供了一個 AuditorAware<T> SPI 介面,您必須實現該介面來告訴基礎架構當前與應用程式互動的使用者或系統是誰。泛型型別 T 定義了用 @CreatedBy@LastModifiedBy 註解的屬性必須是什麼型別。

以下示例展示了一個使用 Spring Security 的 Authentication 物件的介面實現

基於 Spring Security 的 AuditorAware 實現
class SpringSecurityAuditorAware implements AuditorAware<User> {

  @Override
  public Optional<User> getCurrentAuditor() {

    return Optional.ofNullable(SecurityContextHolder.getContext())
            .map(SecurityContext::getAuthentication)
            .filter(Authentication::isAuthenticated)
            .map(Authentication::getPrincipal)
            .map(User.class::cast);
  }
}

該實現訪問 Spring Security 提供的 Authentication 物件,並查詢您在 UserDetailsService 實現中建立的自定義 UserDetails 例項。這裡我們假設您透過 UserDetails 實現暴露了領域使用者,但基於找到的 Authentication,您也可以從任何地方查詢它。

ReactiveAuditorAware

使用響應式基礎架構時,您可能希望利用上下文資訊來提供 @CreatedBy@LastModifiedBy 資訊。我們提供了一個 ReactiveAuditorAware<T> SPI 介面,您必須實現該介面來告訴基礎架構當前與應用程式互動的使用者或系統是誰。泛型型別 T 定義了用 @CreatedBy@LastModifiedBy 註解的屬性必須是什麼型別。

以下示例展示了一個使用響應式 Spring Security 的 Authentication 物件的介面實現

基於 Spring Security 的 ReactiveAuditorAware 實現
class SpringSecurityAuditorAware implements ReactiveAuditorAware<User> {

  @Override
  public Mono<User> getCurrentAuditor() {

    return ReactiveSecurityContextHolder.getContext()
                .map(SecurityContext::getAuthentication)
                .filter(Authentication::isAuthenticated)
                .map(Authentication::getPrincipal)
                .map(User.class::cast);
  }
}

該實現訪問 Spring Security 提供的 Authentication 物件,並查詢您在 UserDetailsService 實現中建立的自定義 UserDetails 例項。這裡我們假設您透過 UserDetails 實現暴露了領域使用者,但基於找到的 Authentication,您也可以從任何地方查詢它。