Bagaimana cara mengetahui pengguna melakukan tindakan hapus di atas meja audit, saat menggunakan login bersama?

8

Informasi latar belakang:

  • Saya membuat koleksi tabel audit untuk melacak pembaruan dan menghapus satu set tabel data untuk aplikasi saya.
  • Catatan audit dibuat melalui pemicu.
  • DML dalam basis data aplikasi saya umumnya akan berasal dari login yang digunakan suatu layanan untuk masuk ke dalam basis data. Karena itu, saya pikir hasil dari SYSTEM_USERakan selalu sama ketika dipanggil dalam sebuah pemicu.
  • Aplikasi saya tidak menyimpan data pengguna saat ini, meskipun string UserIddiberikan kepadanya setiap kali DML dilakukan (dilakukan secara eksklusif dalam prosedur tersimpan).

Masalah yang saya temui adalah ketika pengguna menghapus sebuah catatan, saya ingin tahu siapa yang melakukannya. Karena akan dilakukan dengan login yang sama, saya tidak ingin melihat bahwa semua tindakan dilakukan oleh layanan, saya ingin melihat pengguna mana yang melakukannya. Ini bukan masalah pada pembaruan, karena kami memiliki ModifiedBykolom yang akan diperbarui melalui dikirim UserIdpada pembaruan.

Pertanyaannya adalah: Apakah ada cara untuk mengatur SYSTEM_USERatau memasukkan informasi pengguna ke pemicu saat penghapusan dijalankan?

Ide "terbaik" yang saya miliki saat ini, meskipun saya tidak yakin apakah itu ide yang bagus, adalah bahwa dalam layanan saya memeriksa untuk melihat apakah saat UserIdini ada dalam database sebagai pengguna, dan jika tidak membuat pengguna objek untuk mereka. Kemudian jalankan prosedur tersimpan dengan EXECUTE AS User = @UserId. Kemudian ketika DML dilakukan dalam prosedur tersimpan dan pemicu kebakaran, SYSTEM_USERharus mengembalikan pengguna dari EXECUTE AS.

Jeremy Pridemore
sumber
2
@RBarryYoung Dan mekanisme itu adalah subjek pertanyaan. Layanan saya datang ke database saya melakukan tindakan untuk siapa pun yang memanggilnya, dan saya memiliki UserId tersedia. Saya perlu mencari cara untuk merekam UserId itu dalam kasus penghapusan.
Jeremy Pridemore
Cukup adil, saya harus membaca pertanyaan Anda lebih teliti. Saya pikir saya punya jawaban untuk ini, tetapi saya mungkin tidak dapat mempostingnya sampai larut malam ini.
RBarryYoung

Jawaban:

4

Meskipun menggunakan EXECUTE AS User = @UserIdmungkin merupakan pilihan terbaik Anda (tergantung pada masalah lain), berikut adalah pendekatan alternatif:

Di dalam Anda menyimpan prosedur, atau kapan saja dalam sesi SQL Anda sebelum Anda DELETEmenjalankan perintah berikut:

SET CONTEXT_INFO @UserId

Kemudian di Trigger Anda, Anda dapat mengambil nilai ini dengan

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

Ini memiliki beberapa kelemahan, yang terpenting adalah Anda tidak dapat langsung menggunakan CONTEXT_INFO untuk lebih dari satu hal sekaligus.

RBarryYoung
sumber
Kami memutuskan untuk tidak memiliki informasi untuk saat ini. Jika kita memutuskan kita harus memilikinya, saya akan coba yang ini dulu. Terima kasih untuk idenya.
Jeremy Pridemore
2

Bergantung pada bagaimana Anda mengubah konteks pengguna dari login individual ke login layanan, Anda mungkin menemukan bahwa ORIGINAL_LOGIN () sangat membantu.

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

"Fungsi ini dapat berguna dalam mengaudit identitas konteks penghubung asli. Sedangkan fungsi seperti SESSION_USER dan CURRENT_USER mengembalikan konteks eksekusi saat ini, ORIGINAL_LOGIN mengembalikan identitas login yang pertama kali terhubung ke instance dari SQL Server di sesi itu."

RLF
sumber
Itu fungsi yang rapi, terima kasih telah membawanya. Saya cukup yakin bahwa ketika saya memiliki layanan yang berjalan dan mengenai database dengan login server yang sama setiap kali, maka ORIGINAL_LOGIN () akan selalu mengembalikan pengguna yang menggunakan layanan tersebut. Apakah itu benar bagi Anda?
Jeremy Pridemore
Ya, jika Anda akan melalui akun layanan untuk membuat koneksi ke database, maka ORIGINAL_LOGIN () akan menjadi layanan. Jika Anda mengubah konteks setelah menyambungkan ke database sebagai diri Anda sendiri, maka ORIGINAL_LOGIN () harus menjadi info masuk Anda.
RLF
0

Anda juga dapat mencoba menambahkan Host_Nameke tabel Anda. Saya telah menemukan dalam situasi di mana saya memiliki login bersama saya biasanya dapat melacak seseorang dengan nama mesin mereka sejak 95% dari waktu seseorang bekerja dari mesin mereka sendiri. Itu tidak selalu berhasil, tetapi bisa menjadi informasi sekunder yang bermanfaat.

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

Sayangnya ini tidak akan berfungsi jika Anda bekerja dengan aplikasi web di mana tuan rumah akan selalu menjadi aplikasi web itu sendiri tetapi mungkin patut dicoba.

Kenneth Fisher
sumber