Woher wissen Sie, dass der Benutzer bei Verwendung einer freigegebenen Anmeldung eine Löschaktion für eine Überwachungstabelle ausführt?

8

Hintergrundinformation:

  • Ich erstelle eine Sammlung von Überwachungstabellen, um Aktualisierungen zu verfolgen und eine Reihe von Datentabellen für meine App zu löschen.
  • Audit-Datensätze werden über Trigger erstellt.
  • DML in der Datenbank meiner App stammt im Allgemeinen aus einem Login, mit dem ein Dienst in die Datenbank gelangt. Aus diesem Grund denke ich, dass das Ergebnis von SYSTEM_USERimmer das gleiche sein wird, wenn ein Trigger aufgerufen wird.
  • Meine App speichert derzeit keine Benutzerdaten, obwohl UserIdihr jedes Mal eine Zeichenfolge zugewiesen wird , wenn DML ausgeführt werden soll (ausschließlich in gespeicherten Prozeduren).

Das Problem, auf das ich gestoßen bin, ist, dass ich wissen möchte, wer es getan hat, wenn ein Benutzer einen Datensatz löscht. Da dies durch dieselbe Anmeldung erfolgt, möchte ich nicht sehen, dass alle Aktionen vom Dienst ausgeführt wurden. Ich möchte sehen, welcher Benutzer dies getan hat. Dies ist kein Problem bei einem Update, da wir ModifiedBySpalten haben, die über eine bei UserIdUpdates gesendete Datei aktualisiert werden.

Die Frage ist: Gibt es eine Möglichkeit SYSTEM_USER, die Benutzerinformationen festzulegen oder auf andere Weise in den Trigger zu bekommen, wenn ein Löschvorgang ausgeführt wird?

Die "beste" Idee, die ich derzeit habe, obwohl ich noch nicht sicher bin, ob es eine gute Idee ist, ist, dass ich im Dienst überprüfe, ob sich der aktuelle UserIdals Benutzer in der Datenbank befindet, und wenn nicht, einen Benutzer zu erstellen Objekt für sie. Führen Sie dann gespeicherte Prozeduren mit aus EXECUTE AS User = @UserId. Wenn dann DML in der gespeicherten Prozedur ausgeführt wird und der Trigger ausgelöst wird, SYSTEM_USERsollte der Benutzer von der zurückgegeben werden EXECUTE AS.

Jeremy Pridemore
quelle
2
@RBarryYoung Und dieser Mechanismus ist das Thema der Frage. Mein Dienst kommt in meine Datenbank und führt Aktionen für jeden aus, der ihn aufgerufen hat, und ich habe die Benutzer-ID verfügbar. Ich muss herausfinden, wie diese Benutzer-ID im Falle eines Löschvorgangs aufgezeichnet wird.
Jeremy Pridemore
Fair genug, ich hätte Ihre Frage gründlicher lesen sollen. Ich glaube, ich habe eine Antwort darauf, aber ich kann sie möglicherweise erst spät heute Abend veröffentlichen.
RBarryYoung

Antworten:

4

Während die Verwendung EXECUTE AS User = @UserIdmöglicherweise die beste Option ist (abhängig von anderen Problemen), gibt es hier einen alternativen Ansatz:

Führen Sie in Ihren gespeicherten Prozeduren oder jederzeit in Ihrer SQL-Sitzung DELETEden folgenden Befehl aus, bevor Sie den folgenden Befehl ausführen:

SET CONTEXT_INFO @UserId

Dann können Sie in Ihrem Trigger diesen Wert mit abrufen

SELECT @var = CAST(CAST(CONTEXT_INFO() As Varbinary(4)) As Int)

Dies hat einige Nachteile, von denen der wichtigste darin besteht, dass Sie CONTEXT_INFO nicht ohne weiteres für mehrere Dinge gleichzeitig verwenden können.

RBarryYoung
quelle
Wir haben beschlossen, die Informationen vorerst nicht zu haben. Wenn wir uns entscheiden, dass wir es haben müssen, werde ich es zuerst versuchen. Danke für die Idee.
Jeremy Pridemore
2

Abhängig davon, wie Sie den Benutzerkontext von der individuellen Anmeldung zur Dienstanmeldung ändern, ist ORIGINAL_LOGIN () möglicherweise hilfreich.

http://technet.microsoft.com/en-us/library/ms189492.aspx

"Diese Funktion kann beim Überprüfen der Identität des ursprünglichen Verbindungskontexts hilfreich sein. Während Funktionen wie SESSION_USER und CURRENT_USER den aktuell ausgeführten Kontext zurückgeben, gibt ORIGINAL_LOGIN die Identität des Logins zurück, der in dieser Sitzung zuerst mit der Instanz von SQL Server verbunden war."

RLF
quelle
Das ist eine nette Funktion, danke, dass Sie sie angesprochen haben. Ich bin mir ziemlich sicher, dass ORIGINAL_LOGIN () immer den Benutzer zurückgibt, den der Dienst verwendet, wenn ein Dienst ausgeführt wird und jedes Mal mit demselben Server-Login auf die Datenbank zugreift. Klingt das für Sie richtig?
Jeremy Pridemore
Ja, wenn Sie das Dienstkonto durchlaufen, um die Verbindung zur Datenbank herzustellen, ist ORIGINAL_LOGIN () der Dienst. Wenn Sie den Kontext nach dem Herstellen einer Verbindung zur Datenbank als Sie selbst ändern, sollte ORIGINAL_LOGIN () Ihr Login sein.
RLF
0

Sie können auch versuchen Host_Name, Ihre Tabellen zu ergänzen. Ich habe festgestellt, dass ich in Situationen, in denen ich ein gemeinsames Login habe, eine Person normalerweise anhand ihres Computernamens aufspüren kann, da 95% der Zeit eine Person von ihrem eigenen Computer aus arbeitet. Es funktioniert nicht immer, aber es kann eine nützliche sekundäre Information sein.

SELECT host_name FROM sys.dm_exec_sessions WHERE session_id = @@SPID

Leider funktioniert dies nicht, wenn Sie mit einer Webanwendung arbeiten, bei der der Host immer die Webanwendung selbst sein wird, aber es könnte sich lohnen, es zu versuchen.

Kenneth Fisher
quelle