web-dev-qa-db-ja.com

共有ログインを使用しているときに、監査テーブルで削除アクションを実行しているユーザーを知る方法は?

背景情報:

  • アプリのデータテーブルのセットに対する更新と削除を追跡するために、監査テーブルのコレクションを作成しています。
  • 監査レコードはトリガーを介して作成されます。
  • アプリのデータベースのDMLは通常、サービスがデータベースにアクセスするために使用するログインから取得されます。このため、SYSTEM_USERの結果は、トリガーで呼び出されたときに常に同じになると思います。
  • 私のアプリは現在ユーザーデータを保存していませんが、DMLを実行するたびに文字列UserIdが与えられます(ストアドプロシージャでのみ実行されます)。

私が遭遇した問題は、ユーザーがレコードを削除するときに、誰がそれをしたのか知りたいということです。同じログインによって行われるため、すべてのアクションがサービスによって行われたのではなく、どのユーザーがそれを実行したのかを確認したいと思います。更新時にModifiedByで送信されるを介して更新されるUserId列があるため、これは更新に関する問題ではありません。

問題は:SYSTEM_USERを設定する方法、または削除が実行されたときにユーザー情報をトリガーに取り込む方法はありますか?

私が現在持っている「最良の」アイデアは、それが良いアイデアかどうかはまだわかりませんが、サービスで、現在のUserIdがユーザーとしてデータベースにあるかどうかを確認することです。そうでない場合は、それらのユーザーオブジェクトを作成します。次に、EXECUTE AS User = @UserIdを使用してストアドプロシージャを実行します。次に、ストアドプロシージャでDMLが実行され、トリガーが起動すると、SYSTEM_USEREXECUTE ASからユーザーを返す必要があります。

8

(他の問題によっては)EXECUTE AS User = @UserIdを使用するのが最善の方法かもしれませんが、次の代替アプローチがあります。

ストアドプロシージャ内、またはSQLセッションでDELETEを実行する前の次のコマンドを実行します。

SET CONTEXT_INFO @UserId

次に、トリガーでこの値を取得できます

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

これにはいくつかの欠点がありますが、最も重要なことは、一度に複数のものに対してCONTEXT_INFOを簡単に使用できないことです。

4
RBarryYoung

ユーザーコンテキストを個々のログインからサービスログインに変更する方法によっては、ORIGINAL_LOGIN()が役立つ場合があります。

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

「この関数は、元の接続コンテキストのIDの監査に役立ちます。SESSION_USERやCURRENT_USERなどの関数は現在実行中のコンテキストを返しますが、ORIGINAL_LOGINは、そのセッションでSQL Serverのインスタンスに最初に接続したログインのIDを返します。」

2
RLF

テーブルにHost_Nameを追加してみることもできます。ログインを共有している状況では、95%の人が自分のマシンで作業しているため、通常はマシン名で個人を追跡できます。常に機能するとは限りませんが、有用な副次的な情報になる場合があります。

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

残念ながら、ホストが常にWebアプリケーション自体になるWebアプリケーションを使用している場合、これは機能しませんが、試してみる価値はあります。

0
Kenneth Fisher