# 创建政策

CREATE POLICY — 为表定义新的行级安全策略

# 概要

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

# 描述

创建政策命令为表定义了一个新的行级安全策略。请注意,必须在表上启用行级安全性(使用ALTER TABLE ... 启用行级安全) 以便应用创建的策略。

策略授予选择、插入、更新或删除与相关策略表达式匹配的行的权限。现有表行将根据使用,而将通过创建的新行插入要么更新对照中指定的表达式进行检查带支票.当一个使用表达式对于给定的行返回 true,则该行对用户可见,而如果返回 false 或 null,则该行不可见。当一个带支票表达式为一行返回 true,然后插入或更新该行,而如果返回 false 或 null,则发生错误。

为了插入更新陈述,带支票表达式在之后被强制执行在进行任何实际数据修改之前触发触发器。因此一个行前trigger 可能会修改要插入的数据,影响安全策略检查的结果。带支票表达式在任何其他约束之前强制执行。

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

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

对于可以同时拥有的策略使用带支票表达式 (全部更新), 如果不带支票表达式被定义,那么使用表达式将用于确定哪些行是可见的(正常使用case) 以及允许添加哪些新行 (带支票案子)。

如果为表启用了行级安全性,但不存在适用的策略,则假定“默认拒绝”策略,因此没有行可见或可更新。

# 参数

姓名

要创建的策略的名称。这必须与表的任何其他策略的名称不同。

表名

策略适用的表的名称(可选模式限定)。

允许的

指定将策略创建为许可策略。适用于给定查询的所有许可策略将使用布尔“OR”运算符组合在一起。通过创建许可策略,管理员可以添加可访问的记录集。默认情况下,策略是允许的。

限制性的

指定将策略创建为限制性策略。适用于给定查询的所有限制性策略将使用布尔“AND”运算符组合在一起。通过创建限制性策略,管理员可以减少可以访问的记录集,因为必须为每条记录传递所有限制性策略。

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

命令

策略适用的命令。有效的选项是全部,选择,插入,更新, 和删除.全部是默认值。有关如何应用这些的详细信息,请参见下文。

角色名称

将应用策略的角色。默认是民众,这会将策略应用于所有角色。

using_expression

任何 SQL 条件表达式(返回布尔值)。条件表达式不能包含任何聚合或窗口函数。如果启用了行级安全性,则此表达式将添加到引用表的查询中。表达式返回 true 的行将可见。表达式返回 false 或 null 的任何行对用户都是不可见的(在选择),并且将不可用于修改(在更新要么删除)。这样的行被默默地压制了;没有错误报告。

check_expression

任何 SQL 条件表达式(返回布尔值)。条件表达式不能包含任何聚合或窗口函数。该表达式将用于插入更新如果启用了行级安全性,则对表进行查询。仅允许表达式计算结果为 true 的行。如果对于插入的任何记录或更新产生的任何记录,表达式的计算结果为 false 或 null,则会引发错误。请注意,*check_expression*根据行的建议的新内容而不是原始内容进行评估。

# 每命令策略

全部

使用全部对于策略意味着它将适用于所有命令,无论命令的类型如何。如果全部存在政策并且存在更具体的政策,那么全部政策和更具体的政策(或政策)将被应用。此外,全部策略将应用于查询的选择端和修改端,使用使用两种情况的表达式,如果只有一个使用表达式已定义。

例如,如果一个更新发出,然后全部政策将适用于更新将能够选择要更新的行(应用使用表达式),以及结果更新的行,检查是否允许将它们添加到表中(应用带支票表达式(如果已定义)和使用否则表示)。如果插入要么更新命令尝试向表中添加未通过全部政策的带支票表达式,整个命令将被中止。

选择

使用选择政策意味着它将适用于选择查询和任何时候选择定义策略的关系需要权限。结果是只有来自关系的那些记录通过选择政策将在一个期间返回选择查询,以及需要的查询选择权限,例如更新, 也只会看到那些被允许的记录选择政策。一种选择政策不能有带支票表达式,因为它仅适用于从关系中检索记录的情况。

插入

使用插入政策意味着它将适用于插入命令。插入的行未通过此策略将导致违反策略错误,并且整个插入命令将被中止。一个插入政策不能有使用表达式,因为它仅适用于将记录添加到关系的情况。

注意插入冲突时做更新支票插入政策'带支票仅适用于附加到关系的行的表达式插入小路。

更新

使用更新政策意味着它将适用于更新,选择更新选择分享命令,以及辅助冲突时做更新的条款插入命令。自从更新涉及提取现有记录并用新的修改记录替换它,更新政策同时接受使用表达式和一个带支票表达。这使用表达式确定哪些记录更新命令将看到操作反对,而带支票表达式定义允许将哪些修改的行存储回关系中。

任何更新值未通过带支票表达式将导致错误,整个命令将被中止。如果只有一个使用子句被指定,那么该子句将同时用于使用带支票案例。

通常一个更新命令还需要从正在更新的关系中的列中读取数据(例如,在在哪里子句或返回子句,或在右侧的表达式中条款)。在这种情况下,选择更新的关系也需要权限,并且适当的选择要么全部政策将被应用除了更新政策。因此,用户必须有权访问通过选择要么全部除了被授予通过更新要么全部政策。

当一个插入命令有一个辅助冲突时做更新子句,如果更新路径,首先检查要更新的行使用任何表达更新策略,然后根据带支票表达式。但是请注意,与独立更新命令,如果现有行没有通过使用表达式,将引发错误(更新路径将绝不默默避免)。

删除

使用删除政策意味着它将适用于删除命令。只有通过此策略的行才会被删除命令。可以有通过 a 可见的行选择不能删除的,如果他们没有通过使用的表达删除政策。

在大多数情况下删除命令还需要从要删除的关系中的列中读取数据(例如,在在哪里子句或返回条款)。在这种情况下,选择关系上也需要权利,并且适当的选择要么全部政策将被应用除了删除政策。因此,用户必须有权通过选择要么全部除了被授予删除行的权限之外的策略删除要么全部政策。

一种删除政策不能有带支票表达式,因为它仅适用于从关系中删除记录的情况,因此没有要检查的新行。

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

命令 选择/全部政策 插入/全部政策 更新/所有政策 删除/全部政策
使用表达式 WITH CHECK 表达式 使用表达式 WITH CHECK 表达式 使用表达式
选择 现有行
选择更新/分享 现有行 现有行
插入 新行
插入...返回 新行[一种] 新行
更新 现有行和新行[一种] 现有行 新行
删除 现有行[一种] 现有行
冲突时做更新 现有行和新行 现有行 新行
[一种]如果需要对现有行或新行进行读取访问(例如,在哪里或者返回引用关系中的列的子句)。

# 多重政策的应用

当多个不同命令类型的策略应用于同一命令时(例如,选择更新政策适用于更新命令),则用户必须具有两种类型的权限(例如,从关系中选择行的权限以及更新它们的权限)。因此,一种策略的表达式与另一种策略的表达式使用操作员。

当同一命令类型的多个策略适用于同一命令时,必须至少有一个允许的授予对关系的访问权限的策略,以及所有限制性的政策必须通过。因此所有的允许的策略表达式组合使用或者, 一切限制性的策略表达式组合使用, 并将结果组合使用.如果没有允许的政策,然后访问被拒绝。

请注意,为了组合多个策略,全部策略被视为与正在应用的任何其他类型的策略具有相同的类型。

例如,在一个更新需要两者的命令选择使现代化权限,如果每种类型有多个适用的策略,它们将按如下方式组合:

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
  ...
)

# 笔记

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

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

通常,系统将在用户查询中出现的资格之前,使用安全策略强制实施过滤条件,以防止受保护的数据无意中暴露给用户定义的可能不可信的功能。但是,系统(或系统管理员)标记为防漏的可以在策略表达式之前进行评估,因为它们被认为是可信的。

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

更多的讨论和实践例子可以在第5.8节.

# 兼容性

创建策略是一个PostgreSQL扩展。

# 另见

改变政策,放弃政策,改变桌子