【问题标题】:How can I get the username from a MS Access front end MDW in a SQL back end audit table?如何从 SQL 后端审计表中的 MS Access 前端 MDW 获取用户名?
【发布时间】:2010-09-02 19:25:25
【问题描述】:

我有一个连接到 SQL 服务器后端的 MS Access 2003 mdb 和 mdw。这些表使用系统 DSN 链接。我在 SQL 后端表上有一个触发器,它在插入、更新和删除时将记录插入到另一个后端审计表中。这一切都很好,但是触发器正在使用 system_user 来获取进行记录更改的人,并且该表仅记录 DSN 设置为在链接访问表中进行更改时使用的用户名。如果 DSN 设置为使用通用 sql 用户名“foo”并且 MDW 使用用户特定名称“bar”,则后端的审计表如果将所有用户的所有更改记录为用户“foo”。用户正在使用 mdw 文件登录 mdb,我想在 SQL 后端记录 mdw 中的用户名。这有可能吗?

【问题讨论】:

    标签: sql-server ms-access


    【解决方案1】:

    在 Access VBA 中,您可以使用 CurrentUser() 函数返回 MDW 用户名。您需要找到一种方法来告诉 SQL Server 该名称。如果您从 Access 构建和提交 DML 语句,则可以将 CurrentUser 值添加为字段表达式。

    我对同时使用 Access 用户级安全性和 SQL Server 身份验证感到好奇。乍一看,这听起来像是一种“腰带和吊带”的方法……除了 SQL Server 可以是一个非常有效的腰带,而 Access 用户级安全性是一组相对无效的吊杆。我会质疑 ULS 对您的应用程序有什么好处。

    考虑放弃 ULS 并切换到 SQL Server 的 Windows 身份验证。这可能是一种更简单、更清洁、更安全的方法。

    【讨论】:

    • 他可能需要保护 Access 对象:表单、报告等,而不仅仅是数据。
    • 我当时的想法是,我可以将主机名和 currentuser() 放在 SQL 链接的临时表中。我使用的是 SQL 2008,所以如果我查看 sys.sysprocesses,我可以找到 SPID 和主机名,其中 program_name = 'Microsoft Office 2003'。如果我能找到执行插入/更新/删除触发器的进程的 SPID,那么我可以尝试将主机名绑定到 SPID,并通过我的临时表,回到访问用户名。我只是不知道如何找到在触发器中执行插入/更新/删除的进程的 SPID。
    • 在前端保护 Access 对象可以通过分发 MDE 更好地完成,这使得它们无法编辑。 Jet 用户不太可能需要区分每个用户在前端使用对象的权限。也就是说,您可以在前端使用两个用户轻松设计安全性,管理员(适用于所有人)和另一个用户(可以进行更改的用户)。
    • 我绝对同意@HansUp 的观点,即在前端使用粒度 Jet ULS 可能没有什么好处。即使您继续这样做,为什么不使用 Windows 登录记录您的审计跟踪?这还不够吗?是的,它需要使用 Windows 身份验证,但无论如何这比 SQL 身份验证要容易得多。
    • 前端的表是使用系统DSN链接的,所以对于SQL服务器来说,当实际上有许多不同的用户使用不同的FE时,就好像有多个相同用户登录的实例机器。最重要的是,访问安全性用于在 FE 中为操作定义额外级别的自定义权限(例如,只有 QA 人员可以执行操作 x)。是的,一种方法是将所有内容都转移到 Windows 身份验证中,但这与已经完成的工作相比会有很大的变化。
    【解决方案2】:

    我打赌触发器中的@@spid 可以工作,因为它是由执行 DML 的进程执行的。

    请注意,这可能并不总是可靠的,因为有时 Access 会打开其他连接,而无需任何方式运行您的特殊代码来记录用户对正在使用的 spid。

    更新

    您是否考虑过使用特定于每个 SQL Server 会话的 CONTEXT_INFO 变量?

    DECLARE @Info varbinary(30)
    SET @Info = Convert(varbinary(30), 'My Username')
    SET CONTEXT_INFO @Info
    SELECT Left(Convert(varchar(30), CONTEXT_INFO()), CharIndex(0x0, CONTEXT_INFO()) - 1)
    

    这可能意味着无论如何都要在幕后打桌子,但肯定会比自己动手更快。

    【讨论】:

    • 感谢您提醒我@@SPID。我对那个有一个精神玛格丽塔。解决方案是在服务器中创建一个表来存储 Access 中的主机名和用户名。主窗体打开事件将来自 VBA.Environ("COMPUTERNAME") 和 CurrentUser() 的主机名插入到此表中。在审核触发器中,我使用 Select @UserName = dbo.AccessUsers.Username FROM sys.sysprocesses INNER JOIN dbo.AccessUsers ON sys.sysprocesses.hostname = dbo.AccessUsers.HostName WHERE (sys.sysprocesses.program_name = 'Microsoft Office 2003') 和 sys.sysprocesses.spid = @@SPID
    • 太好了!有什么方法可以存储 spid 而不是实时查找用户名,然后根据 spid 和日期/时间将其转换为用户名(使用具有当前用户历史记录的表)?你这样做的方式很好,最好在触发器中尽可能少地做......
    • 我认为这可能会让用户登录和退出变得混乱。你会得到一个包含重复信息的大表。您必须将时间记录到表中,然后触发访问表以在 SQL 中查找 SPID 或使用 ADO 在访问端进行插入。我同意让触发器做最少的工作,但我认为从长远来看让触发器找到用户名会更干净。如果您能想到更好的方法,我会全力以赴。
    • 有一个特殊的变量,您可以在其中存储特定于会话的数据......让我试着找到它。找到了!查看更新。
    猜你喜欢
    • 2010-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多