Mad*_*ist 5 postgresql row-level-security
我正在使用node-postgres连接到启用了连接池的 PostgreSQL 9.6 数据库。所有连接都使用同一个数据库用户。我不能使用多个数据库用户的一个原因是,据我所知,在这种情况下,行级安全性和视图不能很好地协同工作,因为视图的所有者用于 RLS。
我现在正在考虑在 Postgres 中使用行级安全性,我想确保我这样做是正确的。
我正在使用SET LOCAL
设置当前应用程序用户 ID,然后由行级安全性 USING 子句使用。我能想到通过连接池实现这一点的唯一方法是使用 node-postgres 将每个查询包装在一个事务中,并SET LOCAL
在每个事务中执行如下命令。
SET LOCAL postgres.my_user = 20;
Run Code Online (Sandbox Code Playgroud)
以下代码是我想如何定义行级安全性的简化示例,真实版本还有一些条件:
CREATE POLICY table_a_read_policy ON table_a FOR SELECT
USING (
EXISTS (
SELECT *
FROM permissions
WHERE
user_id = current_setting('postgres.my_user')::int AND
permission_type = 'read'
)
);
Run Code Online (Sandbox Code Playgroud)
我的理解是,在这种情况下,任何 SQL 注入也会使攻击者能够以这种方式设置任何用户 ID 并规避行级安全性。但是我没有看到任何方法可以避免这种情况,因为我连接的数据库用户必须能够查看整个应用程序的所有数据。
有几点我不完全确定:
SET LOCAL
作为存储当前应用程序用户身份以实现行级安全的方式是否安全?尤其是在连接池的上下文中?SET LOCAL
每次执行命令更好的方法?小智 2
我也想做一些类似于你所说的事情。偶然发现这篇博文并发现它很有用。希望这可以帮助。
\n\nblog.2ndquadrant.com/application-users-vs-row-level-security
\n\n\n\n签名会话变量
\n\n第一个解决方案是对会话变量\xe2\x80\x93的简单改进,我们可以\xe2\x80\x99真正阻止用户设置任意值,但是如果我们可以验证该值没有被破坏呢?使用简单的数字签名就可以很容易地做到这一点。可信部分(连接池、应用程序)不仅可以存储用户名,还可以执行以下操作:
\n\n\n\n
signature = sha256(username + timestamp + SECRET)
然后将值和签名存储到会话变量中:
\n\n\n\n
SET my.username = \'username:timestamp:signature\'
假设用户不知道 SECRET 字符串(例如 128B 的随机数据),则\xe2\x80\x99 不可能在不使签名无效的情况下修改该值。
\n