Registrazione di un audit trail (applicazione Java)

3

Sto creando un'applicazione Java (Spring Boot) per la creazione di entità. Ho ottenuto il mio @Controller per ottenere i dati da un front-end Web, ho ottenuto il mio @Service per l'elaborazione dei dati e ho ottenuto il mio @Repository per l'archiviazione permanente delle entità. Quindi, la tua architettura di base semplice e semplice.

Ora, ho bisogno di una traccia di controllo di tutto ciò che accade nel sistema, e per questo ho creato un EventService con metodi storeStartEvent(EntityForm form) , storeFailEvent(EntityForm form, List errors) e storeSavedEvent(Entity entity) . Quindi tre eventi: "inizia a creare un'entità", "Entità creata con successo" e "errore nella creazione di un'entità". EntityForm è solo un oggetto di trasferimento dati che viene utilizzato dal Servizio per creare un'entità effettiva.

Il mio controller si occupa di memorizzare l'evento "avviato" e l'evento "fallimento", in quanto il servizio non è necessario nel primo caso e in quest'ultimo caso il servizio genera un'eccezione che il controllore intercetta. Il Servizio salva comunque l'evento "successo" da solo se riesce a salvare l'Entità con successo.

La mia pista di controllo registra le entità, i parametri e gli indicatori di data e ora, ma mi piacerebbe comunque farlo registrare l'indirizzo IP del client. Questo non è un problema per gli eventi "avviato" e "non riuscito", poiché il Controller conosce l'indirizzo IP del client. Il problema è l'evento "salvato". Ho un metodo service.save(EntityForm form) molto pulito che sto usando, quindi mi sto chiedendo quale sia il modo migliore di procedere.

Opzioni che ho considerato:

  • service.save(EntityForm form, InetAddress ipAddress) sembra semplicemente sbagliato, poiché l'indirizzo IP verrebbe utilizzato solo per scopi di registrazione.

  • service.save(EntityFormWithMetadata form) con un nuovo contenitore contenente l'indirizzo IP sarebbe leggermente migliore, ma per ora sono gli unici metadati, quindi non sono troppo contento di questo neanche.

  • Using a thread local variable. Potrei memorizzare l'indirizzo IP nel controller in una variabile locale del thread e accedervi in EventService. Mi sto appoggiando a questo, ma non lo so.

  • Moving the "saved" event storage into the Controller. Potrei farlo, ma mi piacerebbe assicurarmi che se il sistema ottiene un'altra interfaccia per la creazione di Entità, l'evento "salvato" è ancora registrato. Integrando tale registrazione degli eventi nel metodo save del servizio, è impossibile dimenticare di creare quell'evento.

  • Refactoring the event creation somehow and using somehow using Java @Annotations for methods that need this kind of logging. Questa sarebbe la soluzione più interessante, ma non so come procedere, poiché tutti gli eventi hanno diverse firme: Entity , EntityForm e EntityForm with List .

Qualcuno può fornire qualche informazione?

    
posta ZeroOne 26.04.2016 - 10:32
fonte

3 risposte

2

Using a thread local variable. I could store the IP address in the Controller into a thread local variable and access it in the EventService. I'm leaning towards this one, but I don't know.

Ho usato questo approccio prima, per memorizzare informazioni contestuali sulle richieste. Potrei forse estendere da quanto sopra per archiviare un oggetto contesto di richiesta thread-locale (un attributo di cui sarebbe l'indirizzo IP, potresti anche memorizzare l'id utente richiedente ecc. Ecc.)

È un mezzo semplice e pulito per raggiungere una soluzione che altrimenti avrà un impatto su tutti i percorsi del codice. Penso che sia pulito perché le informazioni contestuali non sono correlate alle singole chiamate di metodo nella logica del programma. Fa affidamento sul server che dà a ciascuna richiesta il proprio thread, ma fino a quando ne viene a conoscenza, penso che sia un approccio utile.

Ho visto questo fatto ad un livello elaborato in cui le informazioni contestuali sono costruite quando la richiesta tocca entità diverse - gli ID entità sono registrati insieme ad eventi significativi - e l'oggetto contestuale risultante è disponibile per la diagnosi futura (essendo persistito separatamente). Fornisce una potente alternativa alla ricerca attraverso i file di registro dei server multi-thread.

    
risposta data 26.04.2016 - 10:48
fonte
1

Suggerirei di spostare tutto il logout dal livello di presentazione e spostarlo nel livello di servizio. In questo modo, se un'altra applicazione vuole creare entità, non perderai le informazioni di registrazione. Potresti avere un metodo createNewEntity() che registra semplicemente l'evento di creazione e restituisce un'entità vuota, mantiene il tuo metodo save() e gestisce anche l'evento di errore nel servizio (che è il luogo in cui ha origine, dopotutto).

    
risposta data 26.04.2016 - 15:32
fonte
1

Penso che dovresti essere in grado di ottenere / memorizzare queste informazioni nei dettagli dell'autenticazione Spring Security (vedi org.springframework.security.core.Authentication#getDetails() ). Dovresti essere in grado di accedervi tramite SecurityContextHolder .

Se vuoi aggiungere ulteriori informazioni al contesto che potresti voler dare un'occhiata link

È fondamentalmente una variabile Thread-Local, ma penso che l'uso delle cose incorporate sia di solito una buona idea specialmente quando si tratta di sicurezza.

    
risposta data 26.04.2016 - 20:44
fonte

Leggi altre domande sui tag