Comment connaître l'utilisateur effectuant une action de suppression sur une table d'audit, lors de l'utilisation d'une connexion partagée?


8

Informations d'arrière-plan:

  • Je crée une collection de tables d'audit pour suivre les mises à jour et les suppressions d'un ensemble de tables de données pour mon application.
  • Les enregistrements d'audit sont créés via des déclencheurs.
  • DML dans la base de données de mon application proviendra généralement d'une connexion qu'un service utilise pour accéder à la base de données. Pour cette raison, je pense que le résultat de SYSTEM_USERsera toujours le même lorsqu'il est appelé dans un déclencheur.
  • Mon application ne stocke pas de données utilisateur actuellement, bien qu'une chaîne lui UserIdsoit donnée à chaque fois que DML doit être fait (fait exclusivement dans les procédures stockées).

Le problème que j'ai rencontré est que lorsqu'un utilisateur supprime un enregistrement, je veux savoir qui l'a fait. Parce que cela se fera par la même connexion, je ne veux pas voir que toutes les actions ont été effectuées par le service, je veux voir quel utilisateur l'a fait. Ce n'est pas un problème sur une mise à jour, car nous avons des ModifiedBycolonnes qui seront mises à jour via un envoyé UserIdsur les mises à jour.

La question est la suivante: existe-t-il un moyen de définir SYSTEM_USERou d'obtenir autrement les informations utilisateur dans le déclencheur lorsqu'une suppression est exécutée?

La "meilleure" idée que j'ai en ce moment, bien que je ne sois pas encore sûre que ce soit une bonne idée, est que dans le service, je vérifie si le courant UserIdest dans la base de données en tant qu'utilisateur, et si ce n'est pas le cas, créez un utilisateur objet pour eux. Exécutez ensuite les procédures stockées avec EXECUTE AS User = @UserId. Ensuite, lorsque DML est terminé dans la procédure stockée et que le déclencheur se déclenche, il SYSTEM_USERdoit renvoyer l'utilisateur à partir du EXECUTE AS.


2
@RBarryYoung Et ce mécanisme fait l'objet de la question. Mon service arrive dans ma base de données en faisant des actions pour celui qui l'a appelé, et j'ai l'ID utilisateur disponible. J'ai besoin de comprendre comment enregistrer cet ID utilisateur dans le cas d'une suppression.
Jeremy Pridemore

D'accord, j'aurais dû lire votre question plus à fond. Je pense avoir une réponse à cela, mais je ne pourrai peut-être pas l'afficher avant tard ce soir.
RBarryYoung

Réponses:


4

Bien que l'utilisation EXECUTE AS User = @UserIdpuisse être votre meilleure option (en fonction d'autres problèmes), voici une approche alternative:

Dans vos procédures stockées, ou à tout moment dans votre session SQL avant d' DELETEexécuter la commande suivante:

SET CONTEXT_INFO @UserId

Ensuite, dans votre déclencheur, vous pouvez récupérer cette valeur avec

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

Cela présente certains inconvénients, dont le plus important est que vous ne pouvez pas facilement utiliser CONTEXT_INFO pour plus d'une chose à la fois.


Nous avons décidé de ne pas disposer des informations pour l'instant. Si nous décidons que nous devons l'avoir, je vais essayer celui-ci en premier. Merci pour l'idée.
Jeremy Pridemore

2

Selon la façon dont vous modifiez le contexte utilisateur de la connexion individuelle à la connexion au service, vous pouvez trouver que ORIGINAL_LOGIN () est utile.

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

"Cette fonction peut être utile pour auditer l'identité du contexte de connexion d'origine. Alors que des fonctions telles que SESSION_USER et CURRENT_USER renvoient le contexte d'exécution actuel, ORIGINAL_LOGIN renvoie l'identité de la connexion qui s'est connectée pour la première fois à l'instance de SQL Server dans cette session."


C'est une fonction intéressante, merci de l'avoir soulevée. Je suis à peu près sûr que lorsque j'ai un service en cours d'exécution et que je frappe la base de données avec la même connexion au serveur à chaque fois, ORIGINAL_LOGIN () renverra toujours l'utilisateur que le service utilise. Cela vous semble-t-il correct?
Jeremy Pridemore

Oui, si vous passez par le compte de service pour établir la connexion à la base de données, alors ORIGINAL_LOGIN () serait le service. Si vous changez de contexte après vous être connecté à la base de données en tant que vous-même, alors ORIGINAL_LOGIN () devrait être votre identifiant.
RLF

0

Vous pouvez également essayer d'ajouter Host_Nameà vos tables. J'ai trouvé dans des situations où j'ai une connexion partagée que je peux généralement retrouver une personne par son nom de machine depuis 95% du temps qu'une personne travaille à partir de sa propre machine. Cela ne fonctionne pas toujours, mais cela peut être une information secondaire utile.

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

Malheureusement, cela ne fonctionnera pas si vous travaillez avec une application Web où l'hôte sera toujours l'application Web elle-même, mais cela peut valoir la peine d'être essayé.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.