使用共享登录名时,如何知道用户对审核表执行删除操作?


8

背景资料:

  • 我正在创建审核表的集合,以跟踪对我的应用程序的一组数据表的更新和删除。
  • 审计记录是通过触发器创建的。
  • 我的应用程序数据库中的DML通常来自服务用于进入数据库的登录名。因此,我认为SYSTEM_USER在触发器中调用时,结果始终是相同的。
  • 我的应用程序当前不存储用户数据,尽管UserId每次执行DML时都会为其分配一个字符串(仅在存储过程中完成)。

我遇到的问题是,当用户删除记录时,我想知道是谁做的。因为它将通过相同的登录完成,所以我不想看到所有操作都是由服务完成的,所以我想看看哪个用户做了。这不是更新的问题,因为我们有一些ModifiedBy列会通过发送更新来UserId更新。

问题是:SYSTEM_USER运行删除操作时,有没有办法将用户信息设置为或以其他方式使用户信息进入触发器?

我现在拥有的“最佳”想法(尽管我不确定这是否是一个好主意)是,在服务中,我检查是否当前UserId作为用户存在于数据库中,如果不是,则创建一个用户为他们反对。然后使用运行存储过程EXECUTE AS User = @UserId。然后,当在存储过程中完成DML并触发触发器时,SYSTEM_USER应从中返回用户EXECUTE AS


2
@RBarryYoung并且该机制是问题的主题。我的服务正在进入我的数据库,对调用它的人进行操作,并且我有可用的UserId。我需要弄清楚在删除的情况下如何记录该UserId。
杰里米·普赖德莫尔

公平地说,我应该更彻底地阅读您的问题。我想我对此有一个答案,但是直到今晚才能发布。
RBarryYoung 2013年

Answers:


4

虽然使用EXECUTE AS User = @UserId也许是最好的选择(取决于其他问题),但这里是另一种方法:

在您的存储过程中,或在DELETE执行以下命令之前的任何时候,在您的SQL会话中:

SET CONTEXT_INFO @UserId

然后在触发器中,您可以使用

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

这有一些缺点,最重要的是您不能一次使用CONTEXT_INFO超过一项。


我们决定暂时没有这些信息。如果我们决定必须拥有它,我将首先尝试它。谢谢你的主意。
杰里米·普里德莫尔

2

根据将用户上下文从单个登录更改为服务登录的方式,可能会发现ORIGINAL_LOGIN()会有所帮助。

http://technet.microsoft.com/zh-CN/library/ms189492.aspx

“此功能在审核原始连接上下文的身份时可能很有用。而诸如SESSION_USER和CURRENT_USER之类的函数将返回当前正在执行的上下文,而ORIGINAL_LOGIN返回在该会话中首次连接到SQL Server实例的登录名。”


这是一个简洁的功能,感谢您提出来。我非常确定,当我运行服务并每次使用相同的服务器登录名访问数据库时,ORIGINAL_LOGIN()总是会返回该服务正在使用的用户。这听起来对吗?
杰里米·普里德摩尔

是的,如果您要通过服务帐户建立与数据库的连接,则ORIGINAL_LOGIN()将成为服务。如果您以自己的身份连接到数据库后更改上下文,则ORIGINAL_LOGIN()应该是您的登录名。
RLF 2013年

0

您也可以尝试添加Host_Name到表中。我发现在具有共享登录名的情况下,由于一个人有95%的时间在自己的计算机上工作,因此通常可以按他们的计算机名称来跟踪某个人。它并不总是有效,但它可能是有用的辅助信息。

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

不幸的是,如果您使用的Web应用程序无法正常工作,而主机始终是Web应用程序本身,则值得尝试。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.