【问题标题】:How should I go about optimizing this row level security policy for reading an event?我应该如何优化此行级安全策略以读取事件?
【发布时间】:2021-08-31 20:14:16
【问题描述】:

这是我用于此策略的表/实体的摘要(简化为 SO)。

user
----
id (pk)

event
-----
uuid (pk)
host_id (fk -> user)
privacy: int

friendship
----------
user_id (pk, fk -> user)
friend_id (pk, fk -> user)

invitation
----------
user_id (pk, fk -> user)
event_uuid (pk, fk -> event)

ENUMS: 
- Privacy (Public, Friends, Private) = (0, 1, 2)

在我的情况下,我想确保,使用 PostgreSQL 中的行级安全性或其他方法(可能是条件?)是用户只能在以下条件之一的情况下看到事件:

  1. 如果他们是活动的主办方
  2. 如果活动的隐私是公开的
  3. 如果活动的隐私是朋友并且他们是活动主持人的朋友
  4. 如果他们被邀请参加活动

我了解这些条件很多,但我不确定检查所有这些条件的最佳格式是什么。目前,这是我用来检查所有这些的 RLS 策略,但它似乎很冗长,我想知道是否有一些我遗漏的东西可以优化它:

create policy read_event
    on event
    for select
    using (
        -- is host
        event.user_id = ?
        or
        -- is public
        event.privacy = 0
        or
        -- is invited
        exists (
            select *
            from invitation as i
            where i.user_id = ? and i.party_uuid = event.uuid
        )
        or
        -- is friends and party is friends-level privacy
        exists (
            select *
            from friendship as f
            where f.user_id = ? and f.friend_id = party.user_id
            or f.user_id = party.user_id and f.friend_id = ?
        )
        and 
        event.privacy = 1
    )

“?”可以用当前用户的 id 进行查询(使用会话变量或其他替代方法)。总的来说,这是我正在尝试做的简化版本,但我只是想看看我是否走在正确的道路上,或者我是否遗漏了什么。

此外,这在某种程度上超出了这个 SO 问题的范围,但如果有人有洞察力,RLS 策略在从其他表加入时是否级联(例如,如果我创建一个带有 fk 的活动邀请,会不会检查 RLS 策略是否在插入时读取事件?)

非常感谢您的帮助!

【问题讨论】:

    标签: sql postgresql security row-level-security


    【解决方案1】:

    我没有检查条件是否符合您的要求,但政策定义看起来很合理。问题是

    • 如果? 与用户没有关联,如何获得它?可以使用占位符参数,但可以随时使用SET 语句更改参数。也许这足以满足您的安全要求。

    • USING 子句中的条件将作为过滤器添加到查询中。它包含OR,因此可能会严重影响查询性能。如果数据,您应该使用实际数量进行测试。

    行级安全适用于每个表。因此,具有外键约束的行的可见性不受被引用表的行级安全策略的影响。

    【讨论】:

    • 我正在设置 ?使用 SET 语句,但它被保护在服务器应用程序的身份验证墙后面。至于另一个项目符号,您对如何改进包含 OR 语句的 USING 子句有什么建议吗?我对此很陌生,所以任何建议都将不胜感激。
    • 如果这是您的情况,您需要ORs。您可以简化条件(例如,通过添加冗余列)或确保过滤器从不处理很多行。
    • 实际上每个exists子句应该只返回一个匹配每个子查询的行,但我不知道这是否意味着过滤器不会处理很多行。
    猜你喜欢
    • 1970-01-01
    • 2023-01-23
    • 2021-10-01
    • 2021-08-06
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    相关资源
    最近更新 更多