web-dev-qa-db-ja.com

監査証跡のロギング(Javaアプリケーション)

エンティティを作成するためのJava(Spring Boot)アプリケーションを作成しています。Webフロントエンドからデータを取得するための@Controllerがあり、データを処理するための@Serviceがあります、エンティティを永続的に保存するための@Repositoryを用意しました。つまり、基本的なシンプルなレイヤーアーキテクチャです。

ここで、システムで発生するすべての監査証跡が必要です。そのために、メソッドstoreStartEvent(EntityForm form)storeFailEvent(EntityForm form, List errors)およびstoreSavedEvent(Entity entity)。したがって、3つのイベント:「エンティティの作成を開始」、「エンティティが正常に作成されました」、「エンティティの作成エラー」。 EntityFormは、実際のエンティティを作成するためにサービスによって使用される単なるデータ転送オブジェクトです。

最初のケースではサービスは不要であり、後者のケースではサービスがコントローラーがキャッチする例外をスローするため、コントローラーは「開始」イベントと「失敗」イベントの格納を処理します。エンティティを正常に保存できた場合、サービスは「成功」イベントを単独で保存します。

私の監査証跡はエンティティ、パラメーター、タイムスタンプを問題なく記録していますが、それでもクライアントのIPアドレスを記録したいと思います。コントローラはクライアントのIPアドレスを認識しているため、「開始」および「失敗」イベントの問題ではありません。問題は「保存された」イベントです。私は使用している非常にクリーンなservice.save(EntityForm form)メソッドを持っているので、続行する最善の方法を考えています。

私が検討したオプション:

  • service.save(EntityForm form, InetAddress ipAddress)は、IPアドレスがロギング目的でのみ使用されるため、正しくないようです。

  • service.save(EntityFormWithMetadata form)には、IPアドレスを含む新しいコンテナーを追加する方が少し良いでしょうが、今のところそれが唯一のメタデータなので、これについてもあまり満足していません。

  • Using a thread local variable.コントローラのIPアドレスをスレッドローカル変数に格納し、EventServiceでアクセスすることができます。私はこれに傾いていますが、わかりません。

  • Moving the "saved" event storage into the Controller.これは可能ですが、システムがエンティティを作成するための別のインターフェースを取得した場合でも、「保存された」イベントが引き続きログに記録されることを確認したいと思います。イベントのログをサービスのsaveメソッドに統合することにより、そのイベントの作成を忘れることはできません。

  • Refactoring the event creation somehow and using somehow using Java @Annotations for methods that need this kind of logging.これは最もクールなソリューションですが、すべてのイベントの署名が異なるため、どのようにすればよいかわかりません:EntityEntityForm、およびEntityForm with List

誰かが洞察を提供できますか?

3
ZeroOne

スレッドローカル変数の使用。コントローラのIPアドレスをスレッドローカル変数に格納し、EventServiceでアクセスできます。私はこれに傾いていますが、わかりません。

リクエストに関するコンテキスト情報を保存するために、このアプローチを以前に使用しました。上記から拡張して、スレッドローカルなリクエストコンテキストオブジェクトを格納します(その属性の1つはIPアドレスです。リクエストしているユーザーIDを格納することもできますなど)。

これは、他の方法ではすべてのコードパスに影響を与えるソリューションを実現するためのクリーンでシンプルな手段です。 contextualの情報はプログラムロジックの個々のメソッド呼び出しとは無関係であるため、問題はないと思います。それはそれ自身のスレッドである各リクエストを与えるサーバーに依存していますが、あなたがそれを知っている限り、私はそれが有用なアプローチだと思います。

これは、リクエストがさまざまなエンティティに触れるとコンテキスト情報が作成される手の込んだ程度に行われるのを見てきました-エンティティIDは重要なイベントとともに記録されます-結果のコンテキストオブジェクトは(個別に永続化することにより)将来の診断に利用できます。マルチスレッドサーバーのログファイルを検索する強力な代替手段を提供します。

2
Brian Agnew

すべてのログをプレゼンテーション層から移動し、サービス層に移動することをお勧めします。そうすれば、別のアプリケーションがエンティティを作成したい場合でも、ロギング情報が失われることはありません。作成イベントをログに記録して空のエンティティを返すcreateNewEntity()メソッドを用意し、save()メソッドを保持して、サービスで障害イベントを処理することもできます(つまり、結局のところ)。

1
TMN

Spring Security Authenticationの詳細でこれらの情報を取得/保存できるはずです(org.springframework.security.core.Authentication#getDetails()を参照)。 SecurityContextHolderを介してアクセスできるはずです。

コンテキストにさらに情報を追加する場合は、次を参照してください http://docs.spring.io/autorepo/docs/spring-security/current/apidocs/org/springframework/security/authentication/AuthenticationDetailsS​​ource .html

基本的にはスレッド固有の変数ですが、特にセキュリティに関しては、組み込みのものを使用することをお勧めします。

1
chromanoid