Auditing

Basics

Spring Data 提供复杂的支持,以透明地跟踪谁创建或更改了实体以及更改发生的时间。要从该功能中受益,你必须使用可以通过注释定义或通过实现接口来定义的审核元数据来装备实体类。此外,还必须通过注释配置或 XML 配置启用审核,以注册所需的架构组件。请参阅特定于存储的章节以获取配置示例。

Spring Data provides sophisticated support to transparently keep track of who created or changed an entity and when the change happened.To benefit from that functionality, you have to equip your entity classes with auditing metadata that can be defined either using annotations or by implementing an interface. Additionally, auditing has to be enabled either through Annotation configuration or XML configuration to register the required infrastructure components. Please refer to the store-specific section for configuration samples.

仅跟踪创建和修改日期的应用程序不需要使其实体类实现 <<`AuditorAware`,审核.审核感知>>。

Applications that only track creation and modification dates are not required do make their entities implement <<`AuditorAware`,auditing.auditor-aware>>.

Annotation-based Auditing Metadata

我们提供 @CreatedBy@LastModifiedBy 来捕获创建或修改实体的用户,以及 @CreatedDate@LastModifiedDate 来捕获更改发生的时间。

We provide @CreatedBy and @LastModifiedBy to capture the user who created or modified the entity as well as @CreatedDate and @LastModifiedDate to capture when the change happened.

An audited entity
class Customer {

  @CreatedBy
  private User user;

  @CreatedDate
  private Instant createdDate;

  // … further properties omitted
}

如你所见,可以有选择地应用注释,具体取决于你想要捕获的信息。用于指示何时进行更改的注释可用于 JDK8 日期和时间类型、longLong 以及旧版 Java DateCalendar 类型的属性。

As you can see, the annotations can be applied selectively, depending on which information you want to capture. The annotations, indicating to capture when changes are made, can be used on properties of type JDK8 date and time types, long, Long, and legacy Java Date and Calendar.

审核元数据不一定需要存在于根级实体中,但可以添加到嵌入式实体中(具体取决于实际使用的存储),如下面的代码段所示。

Auditing metadata does not necessarily need to live in the root level entity but can be added to an embedded one (depending on the actual store in use), as shown in the snippet below.

Audit metadata in embedded entity
class Customer {

  private AuditMetadata auditingMetadata;

  // … further properties omitted
}

class AuditMetadata {

  @CreatedBy
  private User user;

  @CreatedDate
  private Instant createdDate;

}

Interface-based Auditing Metadata

如果你不想使用注释来定义审核元数据,你可以让你的域类实现 Auditable 接口。它公开了所有审核属性的 setter 方法。

In case you do not want to use annotations to define auditing metadata, you can let your domain class implement the Auditable interface. It exposes setter methods for all of the auditing properties.

AuditorAware

如果你使用 @CreatedBy@LastModifiedBy,则审核基础设施在某种程度上需要知道当前主体。为此,我们提供了 AuditorAware<T> SPI 接口,你必须实现该接口才能告诉基础设施与应用程序交互的当前用户或系统是谁。泛型类型 T 定义了用 @CreatedBy@LastModifiedBy 注释的属性必须是什么类型。

In case you use either @CreatedBy or @LastModifiedBy, the auditing infrastructure somehow needs to become aware of the current principal. To do so, we provide an AuditorAware<T> SPI interface that you have to implement to tell the infrastructure who the current user or system interacting with the application is. The generic type T defines what type the properties annotated with @CreatedBy or @LastModifiedBy have to be.

以下示例显示了一个使用 Spring Security 的 Authentication 对象的接口实现:

The following example shows an implementation of the interface that uses Spring Security’s Authentication object:

Implementation of AuditorAware based on Spring Security
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,你也可以从任何地方查找它。

The implementation accesses the Authentication object provided by Spring Security and looks up the custom UserDetails instance that you have created in your UserDetailsService implementation. We assume here that you are exposing the domain user through the UserDetails implementation but that, based on the Authentication found, you could also look it up from anywhere.

ReactiveAuditorAware

在使用响应式基础设施时,你可能希望利用上下文信息来提供 @CreatedBy@LastModifiedBy 信息。我们提供了 ReactiveAuditorAware<T> SPI 接口,你必须实现该接口才能告诉基础设施与应用程序交互的当前用户或系统是谁。泛型类型 T 定义了用 @CreatedBy@LastModifiedBy 注释的属性必须是什么类型。

When using reactive infrastructure you might want to make use of contextual information to provide @CreatedBy or @LastModifiedBy information. We provide an ReactiveAuditorAware<T> SPI interface that you have to implement to tell the infrastructure who the current user or system interacting with the application is. The generic type T defines what type the properties annotated with @CreatedBy or @LastModifiedBy have to be.

以下示例显示了一个使用 Spring Security 响应式 Authentication 对象的接口实现:

The following example shows an implementation of the interface that uses reactive Spring Security’s Authentication object:

Implementation of ReactiveAuditorAware based on Spring Security
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,你也可以从任何地方查找它。

The implementation accesses the Authentication object provided by Spring Security and looks up the custom UserDetails instance that you have created in your UserDetailsService implementation. We assume here that you are exposing the domain user through the UserDetails implementation but that, based on the Authentication found, you could also look it up from anywhere.