監査

基本

Spring Data は、エンティティを作成または変更したユーザーと変更がいつ発生したかを透過的に追跡するための高度なサポートを提供します。この機能を利用するには、アノテーションを使用するか、インターフェースを実装することで定義できる監査メタデータをエンティティクラスに装備する必要があります。さらに、必要なインフラストラクチャコンポーネントを登録するには、アノテーション構成または XML 構成のいずれかを介して監査を有効にする必要があります。構成サンプルについては、ストア固有のセクションを参照してください。

作成日と変更日のみを追跡するアプリケーションでは、エンティティに AuditorAware を実装する必要はありません。

アノテーションベースの監査メタデータ

エンティティを作成または変更したユーザーをキャプチャーする @CreatedBy と @LastModifiedBy、および変更が発生したときにキャプチャーする @CreatedDate と @LastModifiedDate を提供します。

監査対象エンティティ
class Customer {

  @CreatedBy
  private User user;

  @CreatedDate
  private Instant createdDate;

  // … further properties omitted
}

ご覧のとおり、キャプチャーする情報に応じて、アノテーションを選択的に適用できます。変更が行われたときにキャプチャーすることを示すアノテーションは、JDK8 の日付と時刻の型、longLong、レガシー Java Date と Calendar のプロパティで使用できます。

以下のスニペットに示すように、監査メタデータは必ずしもルートレベルのエンティティに存在する必要はありませんが、埋め込まれたエンティティに追加できます(実際に使用されているストアによって異なります)。

埋め込みエンティティのメタデータを監査する
class Customer {

  private AuditMetadata auditingMetadata;

  // … further properties omitted
}

class AuditMetadata {

  @CreatedBy
  private User user;

  @CreatedDate
  private Instant createdDate;

}

インターフェースベースの監査メタデータ

アノテーションを使用して監査メタデータを定義したくない場合は、ドメインクラスに Auditable インターフェースを実装させることができます。すべての監査プロパティの setter メソッドを公開します。

AuditorAware

@CreatedBy または @LastModifiedBy を使用する場合、監査インフラストラクチャは何らかの形で現在のプリンシパルを認識する必要があります。そのために、現在のユーザーまたはアプリケーションと対話するシステムが誰であるかをインフラストラクチャに伝えるために実装する必要がある 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 に基づいて、どこからでも検索できると想定しています。

また、便利な基本クラス AbstractAuditable もあります。これは、インターフェースメソッドを手動で実装する必要を回避するために拡張できます。これにより、ドメインクラスの Spring Data への結合が増加しますが、これは避けたい場合があります。通常、監査メタデータを定義するアノテーションベースのメソッドは、侵襲性が低く、柔軟性が高いため好まれます。

一般的な監査構成

Spring Data JPA には、監査情報のキャプチャーをトリガーするために使用できるエンティティリスナーが付属しています。まず、次の例に示すように、orm.xml ファイル内の永続コンテキストのすべてのエンティティに使用される AuditingEntityListener を登録する必要があります。

例 1: 監査構成 orm.xml
<persistence-unit-metadata>
  <persistence-unit-defaults>
    <entity-listeners>
      <entity-listener class="….data.jpa.domain.support.AuditingEntityListener" />
    </entity-listeners>
  </persistence-unit-defaults>
</persistence-unit-metadata>

次のように、@EntityListeners アノテーションを使用して、エンティティごとに AuditingEntityListener を有効にすることもできます。

@Entity
@EntityListeners(AuditingEntityListener.class)
public class MyEntity {

}
監査機能では、spring-aspects.jar がクラスパス上にある必要があります。

orm.xml が適切に変更され、spring-aspects.jar がクラスパスにある場合、監査機能をアクティブ化するには、次のように Spring Data JPA auditing 名前空間要素を構成に追加します。

例 2: XML 構成を使用した監査のアクティブ化
<jpa:auditing auditor-aware-ref="yourAuditorAwareBean" />

Spring Data JPA 1.5 以降、構成クラスに @EnableJpaAuditing アノテーションを付けることにより、監査を有効にすることができます。ただし、orm.xml ファイルを変更し、クラスパスに spring-aspects.jar を含める必要があります。次の例は、@EnableJpaAuditing アノテーションの使用方法を示しています。

例 3: Java 構成を使用した監査のアクティブ化
@Configuration
@EnableJpaAuditing
class Config {

  @Bean
  public AuditorAware<AuditableUser> auditorProvider() {
    return new AuditorAwareImpl();
  }
}

型 AuditorAware の Bean を ApplicationContext に公開すると、監査インフラストラクチャはそれを自動的に選択し、それを使用してドメイン型に設定する現在のユーザーを決定します。ApplicationContext に複数の実装が登録されている場合、@EnableJpaAuditing の auditorAwareRef 属性を明示的に設定することにより、使用する実装を選択できます。