【问题标题】:Postgresql row level security does not throw errorsPostgresql 行级安全性不会抛出错误
【发布时间】:2019-10-23 11:17:01
【问题描述】:

我有一个 Postgresql 数据库,我想在其中一个表上启用行级别安全性。

一切正常,除了一件事,我希望在用户尝试对他没有权限的记录执行更新时抛出错误。

根据docs

check_expression: 任何 SQL 条件表达式(返回布尔值)。 条件表达式不能包含任何聚合或窗口 职能。此表达式将用于 INSERT 和 UPDATE 查询 如果启用了行级安全性,则针对表。只有行 将允许表达式计算为 true 的值。一个错误会 如果表达式计算结果为 false 或 null 对于任何 插入的记录或更新产生的任何记录。 请注意,check_expression 是根据提议的新的 该行的内容,而不是原始内容。

所以我尝试了以下方法:

CREATE POLICY update_policy ON my_table FOR UPDATE TO editors
    USING (has_edit_privilege(user_name))
    WITH CHECK (has_edit_privilege(user_name));

我还有另一个 SELECT 策略

CREATE POLICY select_policy ON my_table FOR SELECT TO editors 
    USING (has_select_privilege(user_name));

根据文档,这应该创建一个策略,防止编辑角色中的任何人对 my_table 的任何记录执行更新,并在执行更新时抛出错误。这可以正常工作,但不会引发错误。

我的问题是什么? 请帮忙。

【问题讨论】:

  • 上述策略不允许从 my_table 中“选择”。因此,当您尝试 UPDATE 时 - 您尝试更新的行已被过滤掉。如果您允许从 my_table 中选择 - 那么您将收到更新错误。这只是一个快速测试。了解有关内部结构的更多信息会很有趣。
  • @madflow 感谢您的回复,这看起来不是原因。因为我创建了一个允许选择所有记录的策略,但仍然会出现同样的问题。 CREATE POLICY select_policy ON my_table FOR SELECT TO editors USING (true);
  • 好的 - 这是我的测试用例:db-fiddle.com/f/9eHkDZ8JEursvPaLYnRCir/0 .

标签: postgresql


【解决方案1】:

首先,让我解释一下从表中读取时行级安全性的工作原理:

您甚至不必定义策略 - 如果没有针对具有行级安全性的表上的用户的策略,则默认设置是用户什么都看不到。

从表中读取时不会抛出错误。

如果你想抛出错误,你可以写一个函数

CREATE FUNCTION test_row(my_table) RETURNS boolean
   LANGUAGE plpgsql COST 10000 AS
$$BEGIN
   IF /* the user is not allowed */
   THEN
      RAISE EXCEPTION ...;
   END IF;
   RETURN TRUE;
$$END;$$;

然后在您的策略中使用该功能:

CREATE POLICY update_policy ON my_table FOR UPDATE TO editors
    USING (test_row(my_table));

如果可能,我使用COST 10000 函数告诉 PostgreSQL 在所有其他条件之后测试该条件。

这不是万无一失的技术,但它适用于简单的查询。一般情况下可能发生的情况是,某些条件在策略中的条件之后得到检查,这可能会导致查询甚至不会返回行的错误。

但我认为这是滥用行级安全性概念时所能得到的最好结果。

现在让我解释一下写入表:

任何向表中写入不满足CHECK 子句的行的尝试都将导致记录的错误。

现在让我们把它放在一起:

假设您在问题中定义政策:

  • 任何INSERT 都会导致错误。

  • 任何SELECT 都会返回一个空结果。

  • 任何UPDATEDELETE 都会成功,但不会影响任何行。这是因为这些操作在修改数据之前必须读取(扫描)表,并且该扫描不会像SELECT 情况那样返回任何行。由于数据修改不会影响任何行,因此不会引发错误。

【讨论】:

  • 感谢您的回复。我已经更新了这个问题。我想知道为什么我要自己抛出异常,而文档说它会自动抛出?文档还说 USEING 和 WITH CHECK 的参数应该是布尔值,你的函数 test_row 不返回布尔值它只是抛出一个异常,这可以接受吗?
  • 对不起,我没有仔细阅读这个问题。我更新的答案应该涵盖它。
  • 抛出异常而不是返回布尔值会导致问题吗?
  • 正如我所写的,该函数极有可能被其他条件排除的值调用,因此您会在未选择的行中收到错误。
猜你喜欢
  • 2021-05-19
  • 2023-01-12
  • 2021-07-06
  • 1970-01-01
  • 2021-10-01
  • 2018-06-22
  • 2020-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多