8
行安全性策略
除可以通过
GRANT
使用
SQL
标准的
权限
之外,表还可以具有
行安全性策略
,它针对每一个用户限制哪些行可以被普通的查询返回或者可以被数据修改命令插入、更新或删除。这种特性也被称为行级安全性
。默认情况下,表不具有任何策略,这样用户根据 SQL
特权系统具有对表的访问特权,对于查询或更新来说其中所有的行都是平等的。
当在一个表上启用行安全性时(使用
ALTER TABLE
中
ALTER TABLE ... ENABLE ROW LEVEL SECURITY
),所有对该表选择行或者修改行的普通访问都必须被一条行安全性策略所允许(不过,表的拥有者通常不
服从行安全性策略)。如果表上不存在策略,将使用一条默认的否定策略,即所有的行都不可见或者不能被
修改。应用在整个表上的操作不服从行安全性,例如
TRUNCATE
和
REFERENCES
。
行安全性策略可以针对特定的命令、角色或者两者。一条策略可以被指定为适用于
ALL
命令,或者
SELECT
、
INSERT
、
UPDATE
或者
DELETE
。可以为一条给定策略分配多个角色,并且通常的角色成员关系和继承规
则也适用。
要指定哪些行根据一条策略是可见的或者是可修改的,需要一个返回布尔结果的表达式。对于每一行,在
计算任何来自用户查询的条件或函数之前,先会计算这个表达式(这条规则的唯一例外是
leakproof
函
数,它们被保证不会泄露信息,优化器可能会选择在行安全性检查之前应用这类函数)。使该表达式不返回
true
的行将不会被处理。可以指定独立的表达式来单独控制哪些行可见以及哪些行被允许修改。策略表达
式会作为查询的一部分运行并且带有运行该查询的用户的特权,但是安全性定义者函数可以被用来访问对调
用用户不可用的数据。
具有
BYPASSRLS
属性的超级用户和角色在访问一个表时总是可以绕过行安全性系统。表拥有者通常也能绕
过行安全性,不过表拥有者可以选择用
ALTER TABLE
中
ALTER TABLE ... FORCE ROW LEVEL SECURITY
来服从行安全性。
启用和禁用行安全性以及向表增加策略是只有表拥有者具有的特权。
策略的创建可以使用
CREATE POLICY
命令,策略的修改可以使用
ALTER POLICY
命令,而策略的删除可以使
用
DROP POLICY
命令。要为一个给定表启用或者禁用行安全性,可以使用
ALTER TABLE
命令。
每一条策略都有名称并且可以为一个表定义多条策略。由于策略是表相关的,一个表的每一条策略都必须有
一个唯一的名称。不同的表可以拥有相同名称的策略。
当多条策略适用于一个给定的查询时,会把它们用
OR
(对宽容性策略,默认的策略类型)或者
AND
(对限
制性策略)组合在一起。这和给定角色拥有它作为成员的所有角色的特权的规则类似。宽容性策略和限制性
策略在下文将会进一步讨论。
作为一个简单的例子,这里是如何在
account
关系上创建一条策略以允许只有
managers
角色的成员能
访问行,并且只能访问它们账户的行:
CREATE TABLE accounts (manager text, company text, contact_email text);
ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;
CREATE POLICY account_managers ON accounts TO managers
USING (manager
=
current_user);
上面的策略隐含地提供了一个与其该约束适用于被一个命令选择的行(这样一个经理不能
SELECT
、
UPDATE
或者
DELETE
属于其他经理的已有行)以及被一个命令修改的行(这样属于其他经理的行不能通过
INSERT
或者
UPDATE
创建)。
如果没有指定角色或者使用了特殊的用户名
PUBLIC
,则该策略适用于系统上所有的用户。要允许所有用户
访问
users
表中属于他们自己的行,可以使用一条简单的策略:
CREATE POLICY user_policy ON users
USING (user_name
=
current_user);
这个例子的效果和前一个类似。
为了对增加到表中的行使用与可见行不同的策略,可以组合多条策略。这一对策略将允许所有用户查看
users
表中的所有行,但只能修改他们自己的行:
CREATE POLICY user_sel_policy ON users
FOR SELECT
USING (true);
CREATE POLICY user_mod_policy ON users
USING (user_name
=
current_user);
在一个
SELECT
命令中,这两条规则被用
OR
组合在一起,最终的效应就是所有的行都能被选择。在其他
命令类型中,只有第二条策略适用,这样其效果就和以前相同。
也可以用
ALTER TABLE
命令禁用行安全性。禁用行安全性不会移除定义在表上的任何策略,它们只是被
简单地忽略。然后该表中的所有行都是可见的并且可修改,服从于标准的
SQL
特