跳到主要内容

审计

Doubao 中英对照 Auditing

基础​

Spring Data 提供了完善的支持,可以透明地跟踪是谁创建或更改了实体,以及更改发生的时间。要利用此功能,您必须为实体类配备审计元数据,这些元数据可以通过注解或实现接口来定义。此外,必须通过注解配置或 XML 配置来启用审计,以注册所需的基础设施组件。有关配置示例,请参阅特定存储部分。

备注

仅跟踪创建和修改日期的应用程序无需让其实体实现 AuditorAware。

基于注解的审计元数据​

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

class Customer {

@CreatedBy
private User user;

@CreatedDate
private Instant createdDate;

// … further properties omitted
}
java

如您所见,这些注解可以根据您想要捕获的信息选择性地应用。用于指示捕获更改时间的注解,可应用于 JDK8 日期时间类型、long、Long 以及旧版 Java Date 和 Calendar 类型的属性。

时间实例由 org.springframework.data.auditing.DateTimeProvider 提供。默认情况下使用 CurrentDateTimeProvider。可以在启用审计时通过 dateTimeProviderRef 属性进行更改,也可以在 ApplicationContext 中提供专用的 AuditingHandler 或 DateTimeProvider bean。

审计元数据并不一定需要存在于根级实体中,而是可以添加到内嵌实体中(取决于实际使用的存储),如下例代码片段所示。

class Customer {

private AuditMetadata auditingMetadata;

// … further properties omitted
}

class AuditMetadata {

@CreatedBy
private User user;

@CreatedDate
private Instant createdDate;

}
java

基于接口的审计元数据​

如果您不想使用注解来定义审计元数据,可以让您的领域类实现 Auditable 接口。该接口暴露了所有审计属性的 setter 方法。

AuditorAware​

如果您使用了 @CreatedBy 或 @LastModifiedBy,审计基础设施需要以某种方式获知当前主体。为此,我们提供了一个 AuditorAware<T> SPI 接口,您需要实现该接口,以告知基础设施当前与应用程序交互的用户或系统是谁。泛型类型 T 定义了使用 @CreatedBy 或 @LastModifiedBy 注解的属性必须具有的类型。

以下示例展示了使用 Spring Security 的 Authentication 对象实现该接口的方式:

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);
}
}
java

该实现访问 Spring Security 提供的 Authentication 对象,并查找您在 UserDetailsService 实现中创建的自定义 UserDetails 实例。这里我们假设您通过 UserDetails 实现暴露领域用户,但基于找到的 Authentication,您也可以从任何地方查找该用户。

ReactiveAuditorAware​

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

以下示例展示了使用响应式 Spring Security 的 Authentication 对象实现该接口的方式:

class SpringSecurityAuditorAware implements ReactiveAuditorAware<User> {

@Override
public Mono<User> getCurrentAuditor() {

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

该实现访问 Spring Security 提供的 Authentication 对象,并查找您在 UserDetailsService 实现中创建的自定义 UserDetails 实例。这里我们假设您通过 UserDetails 实现暴露领域用户,但基于找到的 Authentication,您也可以从任何地方查找该用户。