¿Cómo saber si el usuario realiza una acción de eliminación en una tabla de auditoría cuando utiliza un inicio de sesión compartido?

8

Información de contexto:

  • Estoy creando una colección de tablas de auditoría para realizar un seguimiento de las actualizaciones y eliminaciones en un conjunto de tablas de datos para mi aplicación.
  • Los registros de auditoría se crean a través de disparadores.
  • El DML en la base de datos de mi aplicación generalmente vendrá de un inicio de sesión que un servicio utiliza para ingresar a la base de datos. Debido a esto, creo que el resultado SYSTEM_USERsiempre será el mismo cuando se llama en un disparador.
  • Mi aplicación no almacena datos de usuario actualmente, aunque UserIdse le asigna una cadena cada vez que se realiza DML (se realiza exclusivamente en procedimientos almacenados).

El problema con el que me encontré es que cuando un usuario elimina un registro, quiero saber quién lo hizo. Debido a que se realizará mediante el mismo inicio de sesión, no quiero ver que todas las acciones se realizaron por servicio, quiero ver qué usuario lo hizo. Esto no es un problema en una actualización, porque tenemos ModifiedBycolumnas que se actualizarán a través de actualizaciones enviadas UserId.

La pregunta es: ¿hay alguna manera de configurar SYSTEM_USERu obtener la información del usuario en el activador cuando se ejecuta una eliminación?

La "mejor" idea que tengo en este momento, aunque no estoy seguro de si es una buena idea todavía, es que en el servicio verifico si el UserIdusuario actual está en la base de datos, y si no es así, creo un usuario objeto para ellos. Luego ejecute procedimientos almacenados con EXECUTE AS User = @UserId. Luego, cuando DML se realiza en el procedimiento almacenado y se dispara el disparador, SYSTEM_USERdebe devolver al usuario de EXECUTE AS.

Jeremy Pridemore
fuente
2
@RBarryYoung Y ese mecanismo es el tema de la pregunta. Mi servicio está llegando a mi base de datos haciendo acciones para quien lo llamó, y tengo el ID de usuario disponible. Necesito descubrir cómo registrar ese UserId en el caso de una eliminación.
Jeremy Pridemore
Justo, debería haber leído tu pregunta más a fondo. Creo que tengo una respuesta para esto, pero es posible que no pueda publicarla hasta tarde esta noche.
RBarryYoung

Respuestas:

4

Durante el uso EXECUTE AS User = @UserId puede ser su mejor opción (dependiendo de otros problemas), aquí hay un enfoque alternativo:

En los procedimientos almacenados, o en cualquier momento de su sesión SQL antes de DELETEejecutar, ejecute el siguiente comando:

SET CONTEXT_INFO @UserId

Luego, en su Trigger puede recuperar este valor con

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

Esto tiene algunas desventajas, la más importante de las cuales es que no puede usar CONTEXT_INFO para más de una cosa a la vez.

RBarryYoung
fuente
Decidimos no tener la información por ahora. Si decidimos que debemos tenerlo, probaré este primero. Gracias por la idea
Jeremy Pridemore
2

Dependiendo de cómo cambie el contexto del usuario del inicio de sesión individual al inicio de sesión del servicio, puede encontrar que ORIGINAL_LOGIN () es útil.

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

"Esta función puede ser útil para auditar la identidad del contexto de conexión original. Mientras que funciones como SESSION_USER y CURRENT_USER devuelven el contexto de ejecución actual, ORIGINAL_LOGIN devuelve la identidad del inicio de sesión que se conectó por primera vez a la instancia de SQL Server en esa sesión".

RLF
fuente
Esa es una función ordenada, gracias por mencionarlo. Estoy bastante seguro de que cuando tengo un servicio ejecutándose y presionando la base de datos con el mismo inicio de sesión del servidor cada vez, ORIGINAL_LOGIN () siempre devolverá al usuario que el servicio está usando. ¿Te parece correcto?
Jeremy Pridemore
Sí, si va a través de la cuenta de servicio para realizar la conexión a la base de datos, entonces ORIGINAL_LOGIN () sería el servicio. Si cambia el contexto después de conectarse a la base de datos como usted mismo, entonces ORIGINAL_LOGIN () debería ser su inicio de sesión.
RLF
0

También podría intentar agregar Host_Namea sus tablas. He encontrado en situaciones en las que tengo un inicio de sesión compartido que generalmente puedo rastrear a un individuo por su nombre de máquina desde el 95% del tiempo que una persona está trabajando desde su propia máquina. No siempre funciona, pero puede ser una información secundaria útil.

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

Lamentablemente, esto no funcionará si está trabajando con una aplicación web en la que el host siempre será la aplicación web en sí, pero puede valer la pena intentarlo.

Kenneth Fisher
fuente