Web 应用程序的基于数据库的审计日志需要用户 ID
Posted
技术标签:
【中文标题】Web 应用程序的基于数据库的审计日志需要用户 ID【英文标题】:Database based audit log for web application needs user id 【发布时间】:2013-08-04 20:33:46 【问题描述】:我有一个 Web 应用程序,它目前只支持 PostgreSQL 作为后端,并且有自己的用户管理。使用 Postgres 身份验证机制使用通用用户帐户完成与数据库的连接。此应用程序现在应该获得一些创建和更改的数据的审核日志,希望仅基于触发器和存储过程,并且出于性能原因,如果一切工作异步且独立于 Web 应用程序,那就太好了。
有一个主要问题:我们想知道 Web 应用程序的哪个用户进行了一些更改或创建了数据,但是该信息通常在开箱即用的存储过程中不可用,因为我们使用泛型连接到 Postgres帐户。我想避免做的是调用 Web 应用程序中的存储过程并以这种方式提供用户 ID,因为这意味着在 Web 应用程序的可能位置添加相关调用。除此之外,我们在没有 Web 应用程序的情况下直接使用数据库对数据模型进行更新,这意味着我们无论如何都需要触发器。
目前,Web 应用程序正在处理从每个请求开始并在其结束时提交的事务。因此,我会在每个请求的事务中创建一个临时表,该表始终获取请求的当前用户 id,该用户 id 应该可用于触发器对创建或更改的数据执行的存储过程。
有些事情我不知道,执行的存储过程是否甚至可以访问数据库的当前事务,从而能够从临时表中检索当前用户 ID?该表不是为其创建触发器的更改数据的一部分。如果在最坏的情况下每个请求都创建一个临时表来存储一个 Integer,性能会受到怎样的影响?如果触发器能够访问临时表,则请求可能随时完成,因为它的工作已完成或出现错误。这将如何影响可以访问临时表的触发器,该临时表仅在事务中退出,因为存储过程想要读取用户 ID,所以该事务被提交或恢复?
有没有其他方法可以将用户 ID 映射到触发器有权访问的事务的某个唯一标识符?除了临时表之外,我还可以创建一个普通表,在该表中,我在每个请求开始时将用户 ID 映射到事务 ID,但与当前事务无关。如果触发器现在将获取负责执行触发器的事务 id,则存储过程可以使用事务 id 来查找使用该事务的用户 id。
有什么想法吗?谢谢!
我添加了一个关于触发器生命周期和执行上下文的问题,适合这个问题:
execution context of database trigger in PostgreSQL
【问题讨论】:
用户之间是否共享数据库会话? 不,目前有一个独特的新数据库连接,每个请求都有一个事务。但我们计划在未来使用某种连接池,它提供生命周期超过一个请求的连接。我们目前不打算改变的是每个请求都包含在一个事务中。 【参考方案1】:如果您可以只使用会话设置,则临时表似乎有点过头了。
直到 9.1 版本,自定义会话变量需要通过 postgresql.conf
声明
custom_variable_classes 参数,这使得它在部署方面有点麻烦。
自 9.2 起,不再需要。所以你可以在连接时发出:
SET myapp.myusername='foobar';
然后在触发器中或实际上在会话中的任何位置,SELECT current_setting('myapp.myusername')
或 SHOW myapp.myusername
将取回该值。
【讨论】:
SET LOCAL
如果您需要事务级别设置,可能会很有用。
触发器是否总是在导致触发器执行的事件发生的客户端会话中完全执行?如果没有,会话值对我没有帮助,因为在触发过程中会话可能已经关闭。如果是,性能可能会受到审计日志记录的影响,我会尽量避免。
我现在也坚持使用 PostgreSQL 8.4,并且需要更改它的配置以获取一些值对我来说听起来并不那么有吸引力。我想我更喜欢我描述的方法或使用后端 pid 在以下 URL 中的方法:depesz.com/2009/08/20/…
@Thorsten: from CREATE TRIGGER doc: 它们 [triggers] 可以在导致触发事件的语句结束时触发,也可以在包含事务结束时触发;在后一种情况下,它们被称为延迟。因此它们永远不会跨越事务边界。
@ThorstenSchöning 会话变量存在于 8.4 中,但您必须更改 postgresql.conf
才能使它们工作。以上是关于Web 应用程序的基于数据库的审计日志需要用户 ID的主要内容,如果未能解决你的问题,请参考以下文章