为什么Postgres视图没有启用行级安全性?

42

我需要严格控制Postgres数据的读写。可更新视图一直以来都能很好地提供对我的数据的严格控制,并允许我添加有价值的计算列。随着Postgres 9.5行级安全性的引入,出现了一种新而强大的控制数据的方式。但是我无法同时使用这两种技术-视图和行级安全。为什么?


1
如果您在表上启用了行级安全性,然后使用可更新的视图对表进行操作,那么安全性是否会失效? - mehmet
4
不行,因为查询通过定义角色的视图进行,而不是当前角色。 - Calebmer
那么,如何在定义的角色视图上设置行级安全性呢? - mehmet
2
我有几个不同的角色访问该视图,因此我失去了那些信息。 - Calebmer
3个回答

35

编辑:正如下面另一条回复提到的那样,自从PostgreSQL 15版本以来,视图可以通过使用security_invoker标志继承其原始表的RLS策略(https://www.postgresql.org/docs/15/sql-createview.html


基本上,由于无法对视图的工作方式进行追溯性更改,因此无法支持对视图的SECURITY INVOKER(或等效)进行支持。据我所知,目前没有这样的功能。
您可以通过行安全性通常来过滤对视图本身的访问。
视图访问的表也将应用其行安全性规则。然而,它们将把current_user视为视图创建者,因为视图以创建/拥有视图的用户的权限访问表(和其他视图)。
如果您愿意参与所需功能的开发,或者在其他情况下,您可以考虑在pgsql-hackers上提出此问题。
也就是说,虽然视图以创建用户的身份访问表并相应更改current_user,但它们不会阻止您使用自定义GUC、session_user或其他上下文信息来进行行安全性策略。您可以在视图中使用行安全性,只是不能(有用地)基于current_user进行过滤。

2
@Calebmer Views访问使用创建视图的用户的访问权限所使用的表。为了使行安全性能够有用地过滤基于访问视图的“顶级”用户访问的表的访问,需要更改视图访问视图中的表的方式,以便不设置current_user等。我们有session_user,但是如果您通过pgbouncer或类似工具使用池化连接,则不会更改它,因此它没有用处。 - Craig Ringer
16
哇.. 这真的需要在政策文档页面中提到。我刚刚在我们的应用程序中发现了这个问题,所有表都在一个私有模式中,它们只能通过不同模式中的视图向外部 API 提供服务。由于这个视图是由超级用户创建的,尽管已经对真实表进行过测试并且正常工作,但 RLS (行级安全性)仍然完全失效了。 - deinspanjer
1
我在那里发布了一条消息,但它正在等待审核。 - deinspanjer
1
似乎是这样的:函数默认设置为SECURITY INVOKER,请参见https://www.postgresql.org/docs/current/sql-createfunction.html。 - Alex
1
那么,为了解决这个问题,应该只需将视图的所有者更改为具有策略的数据库用户吗? - pyramation
显示剩余3条评论

23

从PostgreSQL v15开始,您可以使用视图上的security_invoker选项实现此操作。如果打开该选项,则会将基础表的权限检查为调用视图的用户,并使用调用用户的RLS策略。

您可以使用以下方法更改现有视图:

ALTER VIEW view_name SET (security_invoker = on);

3
如果其他人也需要,该命令是CREATE OR REPLACE VIEW "SomeView" WITH (security_invoker=on) AS SELECT ...。 - Rhuan Barros
但是现在调用用户需要访问底层表才能使视图正常工作。您是否可以同时拥有表抽象和行级安全两个功能? - dnk8n
@dnk8n 有办法的,但不能在评论里面写。 - Laurenz Albe

8

行级安全策略仍然可以应用于视图的 WHERE 子句中,例如:

WHERE my_security_policy_function(person_id)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接