GRANT — 定义访问权限
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[, ...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] )
[, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) }
ON [ TABLE ] table_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { { USAGE | SELECT | UPDATE }
[, ...] | ALL [ PRIVILEGES ] }
ON { SEQUENCE sequence_name [, ...]
| ALL SEQUENCES IN SCHEMA schema_name [, ...] }
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
ON DATABASE database_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON DOMAIN domain_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN DATA WRAPPER fdw_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN SERVER server_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { EXECUTE | ALL [ PRIVILEGES ] }
ON { { FUNCTION | PROCEDURE | ROUTINE } routine_name [ ( [ [ argmode ] [ arg_name ] arg_type [, ...] ] ) ] [, ...]
| ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA schema_name [, ...] }
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON LANGUAGE lang_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
ON LARGE OBJECT loid [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
ON SCHEMA schema_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { CREATE | ALL [ PRIVILEGES ] }
ON TABLESPACE tablespace_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON TYPE type_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT role_name [, ...] TO role_specification [, ...]
[ WITH ADMIN OPTION ]
[ GRANTED BY role_specification ]
其中role_specification可以是:
[ GROUP ] role_name
| PUBLIC
| CURRENT_USER
| SESSION_USER
GRANT 命令有两个基本变体:一种是在数据库对象(表、列、视图、外部表、序列、数据库、外部数据包装器、外部服务器、函数、过程、过程语言、大对象、配置参数、模式、表空间或类型)上授予权限,另一种是授予角色成员资格。这两种变体在许多方面相似,但差异也足够大,因此分别说明。
这种 GRANT 命令变体将数据库对象上的特定权限授予一个或多个角色。如果此前已经授予过某些权限,新授予的权限会加到现有权限之上。
还可以选择在一个或多个模式中,对同一类型的所有对象授予权限。目前仅对表、序列、函数和过程支持这一功能。ALL TABLES 也会影响视图和外部表,这与针对特定对象的 GRANT 命令相同。ALL FUNCTIONS 也会影响聚合函数,但不包括过程,这同样与针对特定对象的 GRANT 命令一致。
关键字 PUBLIC 表示要把权限授予所有角色,包括以后可能创建的角色。PUBLIC 可以视为一个隐式定义的组,并且始终包含所有角色。任何特定角色实际拥有的权限,是直接授予给它的权限、授予给它当前所属任一角色的权限,以及授予给 PUBLIC 的权限之和。
如果指定了 WITH GRANT OPTION,权限接收者随后可以再把该权限授予其他人。没有授予选项时,接收者不能这样做。授予选项不能授予给 PUBLIC。
没有必要向对象拥有者(通常是创建它的用户)授予权限,因为拥有者默认拥有全部权限。(不过,出于安全考虑,拥有者也可以选择撤销自己的某些权限。)
删除对象或以任何方式更改其定义的权利,不被视为一种可授予的权限;它是拥有者固有的,不能被授予或撤销。(不过,可以通过授予或撤销拥有该对象的角色的成员资格,获得类似效果;见下文。)拥有者还隐式拥有该对象上的全部授予选项。
PostgreSQL 会将某些类型对象上的默认权限授予PUBLIC。默认情况下,不会在表、表列、序列、外部数据包装器、外部服务器、大对象、模式或表空间上向PUBLIC授予任何权限。对于其他类型的对象,授予PUBLIC的默认权限如下:数据库上的CONNECT和TEMPORARY(创建临时表)权限;函数和过程上的EXECUTE权限;以及语言和数据类型(包括域)上的USAGE权限。当然,对象所有者可以使用REVOKE撤销默认权限和显式授予的权限。(为了尽可能安全,请在创建对象的同一事务中执行REVOKE,这样其他用户就没有可以使用该对象的时间窗口。)此外,还可以使用ALTER DEFAULT PRIVILEGES命令更改这些初始默认权限设置。
可用权限如下:
SELECT允许使用SELECT读取指定表、视图或序列的任何列,或列出的特定列。还允许使用COPY TO。在UPDATE或DELETE中引用现有列值时也需要此权限。对于序列,此权限还允许使用currval函数。对于大对象,此权限允许读取该对象。
INSERT允许使用INSERT向指定表插入新行。如果列出了特定列,则INSERT命令只能给这些列赋值(其他列因此会获得默认值)。还允许使用COPY FROM。
UPDATE允许使用UPDATE更新指定表的任何列,或列出的特定列。(实际上,任何非简单的UPDATE命令还需要SELECT权限,因为它必须引用表列,以确定要更新的行和/或计算列的新值。)SELECT ... FOR UPDATE和SELECT ... FOR SHARE除了需要SELECT权限外,也要求至少在一列上具有此权限。对于序列,此权限允许使用nextval和setval函数。对于大对象,此权限允许写入或截断该对象。
DELETE允许使用DELETE从指定表删除一行。(实际上,任何非简单的DELETE命令还需要SELECT权限,因为它必须引用表列,以确定要删除的行。)
TRUNCATE允许在指定表上使用TRUNCATE。
REFERENCES允许创建引用指定表或表中特定列的外键约束。(参见CREATE TABLE语句。)
TRIGGER允许在指定表上创建触发器。(参见CREATE TRIGGER语句。)
CREATE对于数据库,允许在数据库中创建新的模式和发布。
对于模式,允许在模式中创建新对象。要重命名现有对象,必须拥有该对象,并且在包含它的模式上具有此权限。
对于表空间,允许在其中创建表、索引和临时文件,也允许创建以该表空间为默认表空间的数据库。(注意,撤销此权限不会改变现有对象的存放位置。)
CONNECT允许用户连接到指定数据库。此权限在连接启动时检查(此外还会检查pg_hba.conf施加的任何限制)。
TEMPORARYTEMP允许在使用指定数据库时创建临时表。
EXECUTE允许使用指定的函数或过程,以及基于该函数实现的任何操作符。这是唯一适用于函数和过程的权限类型。FUNCTION语法也适用于聚合函数。也可以使用ROUTINE来引用函数、聚合函数或过程,而不必区分其具体类型。
USAGE对于过程语言,允许使用指定语言创建以该语言编写的函数。这是唯一适用于过程语言的权限类型。
对于模式,允许访问指定模式中包含的对象(假定也满足对象自身的权限要求)。本质上,这允许被授权者“查找”模式内的对象。没有此权限,仍然可能看到对象名称,例如通过查询系统表。此外,撤销此权限后,现有后端中可能仍有先前已执行过这种查找的语句,因此这并不是阻止对象访问的完全安全的方法。
对于序列,此权限允许使用currval和nextval函数。
对于类型和域,此权限允许在创建表、函数和其他模式对象时使用该类型或域。(注意,它不控制该类型的一般“使用”,例如在查询中出现该类型的值。它仅阻止创建依赖该类型的对象。此权限的主要目的是控制哪些用户可以创建对某个类型的依赖,因为这些依赖可能使所有者以后无法更改该类型。)
对于外部数据包装器,此权限允许使用该外部数据包装器创建新的服务器。
对于服务器,此权限允许使用该服务器创建外部表。被授权者还可以创建、修改或删除与该服务器关联的自己的用户映射。
ALL PRIVILEGES一次授予所有可用权限。PRIVILEGES关键字在PostgreSQL中是可选的,但在严格 SQL 中是必需的。
其他命令所需的权限列在各自命令的参考页面上。
这种GRANT命令变体把一个角色的成员资格授予一个或多个其他角色。角色成员资格之所以重要,是因为它会把授予该角色的权限传递给其每个成员。
如果指定了WITH ADMIN OPTION,成员就可以将该角色的成员资格继续授予其他人,也可以撤销该角色的成员资格。没有管理选项时,普通用户不能这样做。一个角色不被认为在其自身上持有WITH ADMIN OPTION,但是在会话用户与该角色相符的数据库会话中,它可以把自身角色的成员资格授予其他角色,或撤销这种资格。数据库超级用户可以向任何人授予或撤销任何角色的成员资格。具有CREATEROLE权限的角色可以授予或撤销任何非超级用户角色的成员资格。
如果指定了GRANTED BY,该授权会记录为由指定角色执行。只有数据库超级用户可以使用此选项,除非指定的是执行命令的同一角色。
与权限不同,角色成员资格不能授予PUBLIC。还要注意,这种形式的命令不允许把无实际作用的GROUP一词用于role_specification中。
REVOKE 命令用于撤销访问权限。
从 PostgreSQL 8.1 起,用户和组的概念已统一为一种称为角色的单一实体。因此,不再需要使用关键字 GROUP 来标识被授权者是用户还是组。GROUP 仍可出现在命令中,但它只是一个噪声词。
如果用户对某一列本身,或者对其所在整张表拥有该权限,就可以在该列上执行 SELECT、INSERT 等操作。在表级授予某项权限后,再在单列上撤销该权限,并不会产生人们可能期望的效果:表级授权不会受到列级操作的影响。
当对象的非拥有者试图在该对象上执行 GRANT 时,如果该用户在该对象上完全没有任何权限,命令会立即失败。只要有某项权限可用,命令就会继续执行,但只会授予那些该用户持有授予选项的权限。如果未持有任何授予选项,GRANT ALL PRIVILEGES 形式会发出警告;而其他形式如果命令中特别列出的任一权限未持有其授予选项,也会发出警告。(原则上,这些说明也适用于对象拥有者;但由于拥有者总是被视为持有全部授予选项,这种情况实际上不会发生。)
需要注意,数据库超级用户可以访问所有对象,而不受对象权限设置的影响。这可类比于 Unix 系统中的 root 权限。和 root 一样,除非绝对必要,否则不宜以超级用户身份操作。
如果超级用户选择执行 GRANT 或 REVOKE 命令,该命令会像由受影响对象的拥有者发出一样执行。特别是,通过这种命令授予的权限看起来会像是由对象拥有者授予的。(对于角色成员资格,则看起来像是由引导超级用户授予的。)
GRANT 和 REVOKE 也可以由并非受影响对象拥有者的角色执行,只要该角色是拥有该对象之角色的成员,或者是持有该对象上 WITH GRANT OPTION 权限之角色的成员。在这种情况下,权限会记录为由实际拥有该对象的角色,或者由持有 WITH GRANT OPTION 权限的角色授予。例如,如果表 t1 由角色 g1 拥有,而角色 u1 是它的成员,那么 u1 可以把 t1 上的权限授予给 u2,但这些权限看起来会像是直接由 g1 授予的。角色 g1 的任何其他成员之后都可以撤销这些权限。
如果执行 GRANT 的角色通过多条角色成员资格路径间接持有所需权限,则系统不会指明会被记录为执行该授权的是哪一个上层角色。在这种情况下,最佳做法是使用 SET ROLE 切换成你希望作为其身份执行 GRANT 的那个具体角色。
在表上授予权限,并不会自动把权限扩展到该表使用的任何序列,包括绑定到 SERIAL 列的序列。序列上的权限必须单独设置。
使用 psql 的 \dp 命令可以获取表和列的现有权限信息。例如:
=> \dp mytable
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------+---------+-------+-----------------------+--------------------------
public | mytable | table | miriam=arwdDxt/miriam | col1:
: =r/miriam : miriam_rw=rw/miriam
: admin=arw/miriam
(1 row)
由 \dp 显示的条目解释如下:
rolename=xxxx -- privileges granted to a role
=xxxx -- privileges granted to PUBLIC
r -- SELECT ("read")
w -- UPDATE ("write")
a -- INSERT ("append")
d -- DELETE
D -- TRUNCATE
x -- REFERENCES
t -- TRIGGER
X -- EXECUTE
U -- USAGE
C -- CREATE
c -- CONNECT
T -- TEMPORARY
arwdDxt -- ALL PRIVILEGES (for tables, varies for other objects)
* -- grant option for preceding privilege
/yyyy -- role that granted this privilege
上例中的显示结果会出现在用户 miriam 创建表 mytable 并执行以下命令之后:
GRANT SELECT ON mytable TO PUBLIC; GRANT SELECT, UPDATE, INSERT ON mytable TO admin; GRANT SELECT (col1), UPDATE (col1) ON mytable TO miriam_rw;
对于非表对象,还有其他\d命令可以显示其权限。
如果某个对象的“Access privileges”列为空,表示该对象具有默认权限(即其权限列为 null)。默认权限始终包括所有者的全部权限,并且可能根据对象类型包含授予PUBLIC的某些权限,如上所述。在对象上首次执行GRANT或REVOKE时,会先实例化默认权限(例如生成{miriam=arwdDxt/miriam}),然后根据指定请求修改它们。同样,“Column access privileges”中也只会显示具有非默认权限的列的条目。(注意:此处的“默认权限”始终指该对象类型的内置默认权限。权限受ALTER DEFAULT PRIVILEGES命令影响的对象,始终会显示显式权限条目,其中包含ALTER的效果。)
注意,访问权限显示中不会标记所有者隐含的授权选项。只有在显式向某人授予授权选项时,才会出现*。
将表 films 上的插入权限授予所有用户:
GRANT INSERT ON films TO PUBLIC;
将视图 kinds 上的所有可用权限授予用户 manuel:
GRANT ALL PRIVILEGES ON kinds TO manuel;
请注意,如果上述命令由超级用户或 kinds 的拥有者执行,确实会授予所有权限;但如果由其他人执行,则只会授予该执行者持有授予选项的那些权限。
将角色 admins 的成员资格授予用户 joe:
GRANT admins TO joe;
根据 SQL 标准,ALL PRIVILEGES 中的 PRIVILEGES 关键字是必需的。SQL 标准也不支持每条命令对多个对象设置权限。
PostgreSQL 允许对象拥有者撤销自己的普通权限:例如,表拥有者可以通过撤销自己的 INSERT、UPDATE、DELETE 和 TRUNCATE 权限,使该表对自己变成只读。这在 SQL 标准中是不可能的。原因是 PostgreSQL 把拥有者的权限视为拥有者授予给自己的;因此他们也可以撤销这些权限。在 SQL 标准中,拥有者的权限由一个假定实体 “_SYSTEM” 授予。由于拥有者并不是 “_SYSTEM”,因此不能撤销这些权利。
根据 SQL 标准,授予选项可以授予给 PUBLIC;PostgreSQL 只支持将授予选项授予给角色。
SQL 标准允许将GRANTED BY选项用于所有形式的GRANT。PostgreSQL 仅在授予角色成员资格时支持它,即使如此,也只有超级用户可以用它指定其他授权者。
SQL 标准还为其他种类的对象提供 USAGE 权限:字符集、排序规则、翻译。
在 SQL 标准中,序列只有 USAGE 这一项权限,它控制 NEXT VALUE FOR 表达式的使用;该表达式等价于 PostgreSQL 中的 nextval 函数。序列上的 SELECT 和 UPDATE 权限都是 PostgreSQL 扩展。把序列的 USAGE 权限应用到 currval 函数上也是 PostgreSQL 扩展(该函数本身也是扩展)。
数据库、表空间、模式、语言以及配置参数上的权限都是 PostgreSQL 扩展。