表 240.按命令类型应用的策略

CREATE POLICY

创建策略—为表定义新的行级安全策略

Synopsis

CREATE POLICY name ON table_name
    [ AS { PERMISSIVE | RESTRICTIVE } ]
    [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
    [ TO { role_name | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ]
    [ USING ( using_expression ) ]
    [ WITH CHECK ( check_expression ) ]

Description

CREATE POLICY命令为表定义新的行级安全策略。请注意,必须在表上启用行级安全性(使用ALTER TABLE ... ENABLE ROW LEVEL SECURITY),才能应用创建的策略。

策略授予选择,插入,更新或删除与相关策略表达式匹配的行的权限。将对照USING中指定的表达式检查现有的表行,而对照WITH CHECK中指定的表达式检查将通过INSERTUPDATE创建的新行。当USING表达式对于给定的行返回 true 时,则该行对用户可见,而如果返回 false 或 null,则该行不可见。当WITH CHECK表达式的一行返回 true 时,该行将被插入或更新,而如果返回 false 或 null 则将发生错误。

对于INSERTUPDATE语句,在触发BEFORE触发器之后以及进行任何实际数据修改之前,将强制执行WITH CHECK表达式。因此,BEFORE ROW触发器可能会修改要插入的数据,从而影响安全策略检查的结果。 WITH CHECK表达式在任何其他约束之前被强制执行。

策略名称是按表的。因此,一个策略名称可用于许多不同的表,并为每个表定义一个适合该表的定义。

策略可以应用于特定命令或特定角色。除非另有说明,否则新创建的策略的默认设置是它们适用于所有命令和角色。多个策略可能适用于单个命令。请参阅下面的更多细节。 Table 240总结了不同类型的策略如何应用于特定命令。

对于同时具有USINGWITH CHECK表达式(ALLUPDATE)的策略,如果未定义WITH CHECK表达式,则将使用USING表达式来确定哪些行可见(正常USING情况)以及允许哪些新行被添加(WITH CHECK大小写)。

如果为表启用了行级安全性,但是不存在适用的策略,那么将采用“默认拒绝”策略,这样就不会显示或更新任何行。

Parameters

请注意,在限制性策略可以有效地用于减少记录访问之前,至少需要一个许可策略来授予对记录的访问权限。如果仅存在限制性策略,则将无法访问任何记录。当存在宽松策略和限制性策略的混合时,除了所有限制性策略之外,仅当至少一项宽松策略通过时,才可以访问记录。

Per-Command Policies

例如,如果发出了UPDATE,则ALL策略将同时适用于UPDATE能够选择哪些行作为要更新的行(应用USING表达式)以及所产生的更新行,以检查它们是否适用允许将其添加到表中(如果定义了,则应用WITH CHECK表达式,否则应用USING表达式)。如果INSERTUPDATE命令尝试向表中添加未通过ALL策略的WITH CHECK表达式的行,则整个命令将被中止。

请注意,INSERTON CONFLICT DO UPDATE仅检查INSERT路径附加到关系的行的INSERT策略的WITH CHECK表达式。

更新值未通过WITH CHECK表达式的任何行都将导致错误,并且整个命令将被中止。如果仅指定USING子句,则该子句将同时用于USINGWITH CHECK情况。

通常,UPDATE命令还需要从要更新的关系中的列中读取数据(例如,在WHERE子句或RETURNING子句中,或在SET子句右侧的表达式中)。在这种情况下,还需要对更新的关系具有SELECT权限,并且除了UPDATE策略之外,还将应用适当的SELECTALL策略。因此,除了被授予通过UPDATEALL策略更新行的权限之外,用户还必须有权访问通过SELECTALL策略更新的行。

INSERT命令具有辅助ON CONFLICT DO UPDATE子句时,如果采用UPDATE路径,则首先针对任何UPDATE策略的USING表达式检查要更新的行,然后针对WITH CHECK表达式检查新的更新的行。但是请注意,与独立的UPDATE命令不同,如果现有行未传递USING表达式,则将引发错误(*绝不会避免UPDATE路径)。

在大多数情况下,DELETE命令还需要从要删除的关系中的列中读取数据(例如,在WHERE子句或RETURNING子句中)。在这种情况下,该关系上还需要SELECT权限,并且除了DELETE策略之外,还将应用适当的SELECTALL策略。因此,除了被授予通过DELETEALL策略删除行的权限之外,用户还必须有权访问通过SELECTALL策略删除的行。

DELETE策略不能具有WITH CHECK表达式,因为它仅适用于从关系中删除记录的情况,因此没有要检查的新行。

Command SELECT/ALL policy INSERT/ALL policy UPDATE/ALL policy DELETE/ALL policy
USING expression WITH CHECK expression USING expression WITH CHECK expression USING expression
SELECT Existing row
SELECT FOR UPDATE/SHARE Existing row Existing row
INSERT New row
INSERT ... RETURNING 新行[a] New row
UPDATE 现有行和新行[a] Existing row New row
DELETE 现有的[a] Existing row
ON CONFLICT DO UPDATE 现有和新行 Existing row New row
[a]如果需要对现有或新行进行读取访问(例如,引用该关系中的列的WHERERETURNING子句)。

多种 Policy 的应用

当不同命令类型的多个策略应用于同一命令(例如,SELECTUPDATE策略应用于UPDATE命令)时,用户必须同时具有两种类型的权限(例如,从关系中选择行的权限以及进行更新的权限)。因此,使用AND运算符将一种策略类型的表达式与另一种策略类型的表达式组合在一起。

当同一命令类型的多个策略应用于同一命令时,则必须至少有一个PERMISSIVE策略授予对该关系的访问权限,并且所有RESTRICTIVE策略都必须通过。因此,使用OR组合所有PERMISSIVE策略表达式,使用AND组合所有RESTRICTIVE策略表达式,使用AND组合结果。如果没有PERMISSIVE策略,则拒绝访问。

请注意,出于组合多个策略的目的,ALL策略被视为与所应用的其他任何类型的策略具有相同的类型。

例如,在同时要求SELECTUPDATE权限的UPDATE命令中,如果每种类型都有多个适用的策略,则将它们组合如下:

expression from RESTRICTIVE SELECT/ALL policy 1
AND
expression from RESTRICTIVE SELECT/ALL policy 2
AND
...
AND
(
  expression from PERMISSIVE SELECT/ALL policy 1
  OR
  expression from PERMISSIVE SELECT/ALL policy 2
  OR
  ...
)
AND
expression from RESTRICTIVE UPDATE/ALL policy 1
AND
expression from RESTRICTIVE UPDATE/ALL policy 2
AND
...
AND
(
  expression from PERMISSIVE UPDATE/ALL policy 1
  OR
  expression from PERMISSIVE UPDATE/ALL policy 2
  OR
  ...
)

Notes

您必须是表的所有者才能为其创建或更改策略。

尽管策略将用于对数据库中的表进行显式查询,但是当系统执行内部参照完整性检查或验证约束时,策略将不会应用。这意味着可以通过间接方式确定给定值的存在。例如,尝试将重复值插入到为主键或具有唯一约束的列中。如果插入失败,则用户可以推断该值已经存在。 (此示例假定策略允许用户插入他们不允许查看的记录.)另一个示例是允许用户将其插入引用另一个表(否则为隐藏表)的表中。用户可以通过将值插入到引用表中来确定其存在,如果成功,则表明该值存在于引用表中。可以通过精心设计策略来防止用户完全无法插入,删除或更新记录(这些记录可能表明他们原本无法查看的值)或使用生成的值(例如,替代键)来解决这些问题。而不是具有外部含义的键。

通常,系统将在出现在用户查询中的资格之前强制执行使用安全策略强加的筛选条件,以防止将受保护的数据无意中暴露给可能不值得信赖的用户定义功能。但是,系统(或系统 Management 员)标记为LEAKPROOF的功能和运算符可能会在策略表达式之前进行评估,因为它们被认为是可信任的。

由于策略表达式是直接添加到用户查询中的,因此它们将以运行整个查询的用户权限运行。因此,使用给定策略的用户必须能够访问该表达式中引用的任何表或函数,否则在尝试查询已启用行级安全性的表时,他们将仅收到权限拒绝错误。但是,这不会改变视图的工作方式。与普通查询和视图一样,视图引用的表的权限检查和策略将使用视图所有者的权限以及适用于该视图所有者的任何策略。

其他讨论和实际示例可以在Section 5.7中找到。

Compatibility

CREATE POLICY是 PostgreSQL 扩展。

See Also

ALTER POLICY, DROP POLICY, ALTER TABLE

上一章 首页 下一章