I flera av de projekt vi har arbetat med har kunder bett oss att logga fler användaråtgärder i databasen. De vill veta alla de åtgärder som användarna utför i applikationen, men att fånga och registrera alla mänskliga interaktioner kan vara utmanande. Vi var tvungna att logga alla ändringar av data som utfördes via systemet. Den här artikeln beskriver några av de fallgropar vi stötte på och de metoder vi använde för att övervinna dem.
Introduktion
Jag arbetar som lösningsarkitekt inom finansiella tjänster. Det är viktigt att hålla ett register över den senaste användaren som ändrade en rad. I de enklaste fallen räcker det att registrera tidsstämpeln för ändringen för att ha spårbarhet av förändringar. Här är ett enkelt exempel på en tabell som lagrar kundavtal som inkluderar last_changed
kolumner för användare och tidsstämpel.
Men i vissa fall är detta inte tillräckligt. Vi måste ofta ha full spårbarhet (inklusive före och efter "bilder" av uppgifterna). I vissa fall behöver vi också revisionsbarhet (vem, vad, när).
Tyvärr var många av våra system inte utformade för att ge spårbarhet och granskning. Vi behövde reverse engineering dessa verksamhetskrav in i systemen.
Spårbarhet
I vissa fall har vi funnit spårbarhet lätt att uppnå. Medan vi i andra har funnit det svårt eller till och med omöjligt. Beroende på ditt system kan lösningen vara enkel. Din dataåtkomst kan möjliggöra en enkel injektion av loggning av före- och efterbilder av data. Denna loggning kan implementeras så att resultaten lagras i en databastabell snarare än i en loggfil. I vissa produkter uppnådde vi detta på ett enkelt sätt genom uthålligheten lager. Detta var till exempel möjligt med Hibernate .
Här kan du se en post för varje revisionsspårpost, plus att det kommer att finnas före- och eftervärden för varje kolumn som har ändrats. Dessutom, om en rad raderas, sparar vi den informationen med functioncode
anger radera. Vi har valt att använda varchar(1) för att lagra koden för funktionen (C, R, D) som anger typen av modifiering, snarare än namnet eller beskrivningen av "operationen" (Create, Update, Delete) som utfördes . instance_key
innehåller den primära nyckeln för objektet som lades till, modifierades eller togs bort, för spårbarhet.
Ändå kan det vara så att ditt dataåtkomstlager inte tillhandahåller den nödvändiga funktionaliteten för dig. För andra produkter gjorde inte vårt lager för dataåtkomst. I dessa fall krävde spårbarheten komplexa förändringar. Till exempel kan du behöva hämtning och loggning av eventuella data före ändring. Som jag skrev är detta möjligt men kan vara komplicerat att införa. Utvecklare måste skapa en hämtning av varje rad innan de ändrar en rad. Det skulle inte vara möjligt för en uppdatering att köras utan ett urval.
Hur kan du arbeta kring spårbarhet? En möjlig lösning är att se till att du känner till startsituationen för all data, det vill säga startsituationen som skapas av eventuell statisk data som laddas in i systemet. Sedan måste du logga alla ändringar. Med andra ord, vilka är alla "efter"-bilder av data? På så sätt skulle det vara möjligt att "rulla framåt ” från inlästa statiska data. Alla uppdateringar som gjorts fram till den tidpunkten tillämpas. Detta är en mindre idealisk situation, men kan vara acceptabel.
En enkel tabell kan användas om den enda tillgängliga informationen är det nya värdet och inte det tidigare värdet.
Revisionsbarhet
I vissa situationer måste vi se till att alla åtgärder som vidtas i systemet är fullt reviderbara . Vem loggade in vid vilken tid? Vilka åtgärder vidtog varje användare i systemet, inklusive att bara visa data? Detta är viktigt eftersom det kan vara viktigt om en användare tittade på en betalning.
För att uppnå finkornig spårning kan vara svårt att bara titta på databasåtkomst. Vi måste ofta titta på en högre nivå och granska de handlingar eller tjänster som utförs. I vissa fall kunde vi spåra varje servicesamtal för att veta vad en användare gjorde vid vilken tidpunkt. Med en in-/utdatastyrenhet för webbtjänster var loggningen av tjänstförfrågningar ganska enkel.
Här är ett exempel på en enkel användarrevisionslogg där vi registrerar den åtgärd som varje användare utför. Jag diskuterar några frågor om detta tillvägagångssätt i nästa avsnitt "Bevis".
En kort tabellbeskrivning ges nedan:
user_audit
Tabellen innehåller datagranskningsposter som är tidsstämplade. Den primära nyckeln består av audit_entry_time
stämpel plus user_id
och bank_id
plus namnet på action
genomförde. Fälten har betydelser som motsvarar deras namn. Granskningstabellen lagrar result
av åtgärden, plus den faktiska class
som utförde åtgärden, dess indata parameters
och eventuella errors
.
Här är ytterligare ett exempel på ett granskningsspår där vi registrerar före- och efterbilder av data som har ändrats i en viss tabell (tillsammans med utförd åtgärd, användaruppgifter och tidsstämpel).
audit_trail
Tabellen innehåller granskningsposter av före- och efterbilder av data. Den primära nyckeln består av audit_gen_key
det är en nyckel som genereras av applikationen. Fälten har betydelser som motsvarar deras namn. Namnet på databastabellen för vilken denna revisionsspårpost är registrerad lagras i modified_table
, plus att "före"-bilden lagras i prev_value
och "efter"-bilden i new_value
. module
som utför ändringen och funct_type
ändringar (Skapa, Uppdatera, Ta bort) lagras också. Slutligen, revisionsinformationen för user_id
(och motsvarande bank_id
) plus tidsstämpeln för ändringen (date_last_changed
).
Då fick vi en utmaning. Vid loggning av både spårbarhetsinformation och granskningsinformation sker loggning två gånger. Ur revisionssynpunkt är detta irriterande. Revisorer måste se till att informationen är densamma mellan dessa två loggar.
Bevis
En annan utmaning var att säkerställa loggning av alla användaråtgärder . Detta krävs ofta av revisorer inom finansbranschen.
Nu har vi en riktig utmaning. Vår lösning var att säkerställa central spårbarhet och granskningsloggning. Centrala "gränssnitt" säkerställer att alla implementeringar av det gränssnittet inkluderar loggning. Det var enkelt att se till att alla lämpliga klasser implementerade gränssnittet.
Naturligtvis garanterar detta inte 100% bevis på loggning. Det är en stark säkerhetskontroll att alla lämpliga klasser loggades efter behov.
Slutsats
Omvänd konstruktion av ny affärsfunktionalitet i ett befintligt system är alltid en utmaning. Detta kan vara ännu mer fallet när den implementerade funktionen går till kärnan.