5.8. 权限 #
一旦一个对象被创建,它会被分配一个所有者。所有者通常是执行创建语句的角色。对于大部分类型的对象,初始状态下只有所有者(或者超级用户)能够对该对象做任何事情。为了允许其他角色使用它,必须分配权限。
有不同种类的权限:SELECT、INSERT、UPDATE、DELETE、TRUNCATE、REFERENCES、TRIGGER、CREATE、CONNECT、TEMPORARY、EXECUTE、USAGE、SET、ALTER SYSTEM 以及 MAINTAIN。适用于特定对象的权限取决于对象的类型(表、函数等)。有关这些权限含义的更多详细信息如下所示。后续的各节和各章还将展示这些权限是如何使用的。
修改或销毁一个对象的权利是该对象所有者固有的权利,其本身不能被授予或撤销。(但是,与所有权限一样,该权利可以由拥有该对象的角色的成员继承;请参阅第 21.3 节。)
一个对象可以通过该对象类型相应的 ALTER 命令来重新分配所有者,例如
ALTER TABLEtable_nameOWNER TOnew_owner;
超级用户总是可以做到这点,普通角色只有在同时是对象的当前所有者(或者继承对象所有者角色的权限)并且能够对新的所有者角色执行 SET ROLE 时,才能做同样的事。旧所有者的所有对象权限会随所有权一起转移给新所有者。
分配权限使用 GRANT 命令。例如,如果 joe 是一个已有角色,并且 accounts 是一个已有表,则可以用以下命令授予更新该表的权限:
GRANT UPDATE ON accounts TO joe;
用 ALL 代替某个具体权限,会授予与该对象类型相关的全部权限。
特殊的“角色”名 PUBLIC 可用于向系统中的每个角色授予权限。此外,当数据库用户很多时,可以设置“组”角色来协助管理权限 — 详见第 21 章。
要撤销之前授予的权限,使用名称贴切的 REVOKE 命令:
REVOKE ALL ON accounts FROM PUBLIC;
通常,只有对象的拥有者(或超级用户)可以授予或撤销对象上的权限。不过,也可以在授予权限时“附带授权选项”,使接收者有权进一步将该权限授予其他角色。如果之后撤销了授权选项,所有直接或经过授权链从该接收者取得此权限的角色都会失去权限。详见 GRANT 和 REVOKE 参考页。
对象的所有者可以选择撤销自己的普通权限,例如,令表对于自己和其他人只读。但是所有者总是被视为拥有所有的授予选项,所以他们总是可以重新授予自己的权限。
可用的权限如下:
SELECT#允许从表、视图、物化视图或其他类似表的对象的任何列或特定列进行
SELECT。还允许使用COPY TO。这个权限还需要用于引用UPDATE、DELETE或MERGE中的现有列值。对于序列,这个权限还允许使用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#允许创建引用表或表的特定列的外键约束。授予此权限时应格外谨慎,因为创建外键的用户可以安排让外键约束检查调用任意函数(例如类型转换函数),而这些函数将以表所有者的权限调用。
TRIGGER#允许在表、视图等上创建触发器。授予此权限时应格外谨慎,因为添加到表或视图的任何触发器都将以修改它的用户的权限执行。
CREATE#对于数据库,允许在数据库中创建新的模式和发布,并允许在数据库中安装受信任的扩展。
对于模式,允许在模式中创建新对象。要重命名已有对象,必须拥有该对象并且具有其所在模式的此权限。
对于表空间,允许在其中创建表、索引和临时文件,并允许创建以该表空间为默认表空间的数据库。
注意,撤销此权限不会改变已有对象的存在状态或位置。
CONNECT#允许被授权者连接到数据库。此权限在连接启动时进行检查(此外还会检查
pg_hba.conf强加的任何限制)。TEMPORARY#允许在使用该数据库时创建临时表。
EXECUTE#允许调用函数或过程,包括使用基于该函数实现的任何操作符。这是唯一适用于函数和过程的权限类型。
USAGE#对于过程语言,允许在该语言中创建函数。这是唯一适用于过程语言的权限类型。
对于模式,允许访问包含在模式中的对象(假设对象自身的权限要求也得到满足)。本质上,这允许被授权者“查找”模式中的对象。没有这个权限,仍然可以看到对象名称,例如,通过查询系统目录。此外,在撤销此权限后,现有会话可能有先前执行此查找的语句,因此这不是完全安全的防止对象访问的方式。
对于序列,允许使用
currval和nextval函数。对于类型和域,允许在表、函数和其他模式对象的创建中使用该类型或域。(请注意,此权限并不控制类型的所有“使用”,比如类型值出现在查询中。它只是防止依赖于该类型的对象被创建。此权限的主要目的是控制哪些用户可以创建对类型的依赖,而这种依赖可能使所有者以后无法更改类型。)
对于外部数据包装器,允许使用外部数据包装器创建新的服务器。
对于外部服务器,允许使用该服务器创建外部表。被授权者还可以创建、修改或删除与该服务器关联的自己的用户映射。
SET#允许在当前会话中将服务器配置参数设置为新值。(虽然可以在任何参数上授予此权限,但除了通常需要超级用户权限设置的参数外,这是没有意义的。)
ALTER SYSTEM#允许使用 ALTER SYSTEM 命令将服务器配置参数配置为新值。
MAINTAIN#允许在关系上执行
VACUUM、ANALYZE、CLUSTER、REFRESH MATERIALIZED VIEW、REINDEX和LOCK TABLE。
其他命令所需的权限列在各自命令的参考页中。
PostgreSQL 在创建对象时,默认情况下将某些类型的对象的权限授予 PUBLIC。默认情况下,表、表列、序列、外部数据包装器、外部服务器、大对象、模式、表空间或配置参数不授予 PUBLIC 任何权限。对于其他类型的对象,默认授予 PUBLIC 的权限如下:数据库的 CONNECT 和 TEMPORARY(创建临时表)权限;函数和存储过程的 EXECUTE 权限;以及语言和数据类型(包括域)的 USAGE 权限。对象所有者当然可以 REVOKE 默认和明确授予的权限。(为了最大安全性,在创建对象的同一个事务中发出 REVOKE;这样就不会留下其他用户可以使用该对象的时间窗口。)此外,可以使用 ALTER DEFAULT PRIVILEGES 命令覆盖这些默认权限设置。
表 5.1 显示了 ACL(访问控制列表)值中用于这些权限类型的单字母缩写。你将在下面列出的 psql 命令的输出中,或者在查看系统目录的 ACL 列时看到这些字母。
表 5.1. ACL 权限缩写
| 权限 | 缩写 | 适用对象类型 |
|---|---|---|
SELECT | r(“读取”) | LARGE OBJECT、SEQUENCE、TABLE(以及类似表的对象)、表列 |
INSERT | a(“追加”) | TABLE、表列 |
UPDATE | w(“写入”) | LARGE OBJECT、SEQUENCE、TABLE、表列 |
DELETE | d | TABLE |
TRUNCATE | D | TABLE |
REFERENCES | x | TABLE、表列 |
TRIGGER | t | TABLE |
CREATE | C |
DATABASE、SCHEMA、TABLESPACE
|
CONNECT | c | DATABASE |
TEMPORARY | T | DATABASE |
EXECUTE | X | FUNCTION、PROCEDURE |
USAGE | U |
DOMAIN、FOREIGN DATA WRAPPER、FOREIGN SERVER、LANGUAGE、SCHEMA、SEQUENCE、TYPE
|
SET | s | PARAMETER |
ALTER SYSTEM | A | PARAMETER |
MAINTAIN | m | TABLE |
表 5.2 使用上面所示的缩写总结了每种类型 SQL 对象可用的权限。它还显示了可用于检查每种对象类型权限设置的 psql 命令。
表 5.2. 访问权限摘要
| 对象类型 | 所有权限 | 默认 PUBLIC 权限 | psql 命令 |
|---|---|---|---|
DATABASE | CTc | Tc | \l |
DOMAIN | U | U | \dD+ |
FUNCTION 或 PROCEDURE | X | X | \df+ |
FOREIGN DATA WRAPPER | U | 无 | \dew+ |
FOREIGN SERVER | U | 无 | \des+ |
LANGUAGE | U | U | \dL+ |
LARGE OBJECT | rw | 无 | \dl+ |
PARAMETER | sA | 无 | \dconfig+ |
SCHEMA | UC | 无 | \dn+ |
SEQUENCE | rwU | 无 | \dp |
TABLE(以及类似表的对象) | arwdDxtm | 无 | \dp |
| 表列 | arwx | 无 | \dp |
TABLESPACE | C | 无 | \db+ |
TYPE | U | U | \dT+ |
特定对象上已授予的权限显示为 aclitem 条目列表,每个条目的格式如下:
grantee=privilege-abbreviation[*].../grantor
每个 aclitem 列出了由特定授权者授予某个被授权者的全部权限。具体权限由表 5.1 中的单字母缩写表示;如果该权限带有授予选项,则会附加*。例如,calvin=r*w/hobbes 表示角色 calvin 具有 SELECT 权限(r)并带有授予选项(*),同时还具有不可转授的 UPDATE 权限(w),这两项权限都由角色 hobbes 授予。如果 calvin 还拥有由其他授权者授予的同一对象上的某些权限,这些权限会显示为单独的 aclitem 条目。aclitem 中空的被授权者字段代表 PUBLIC。
例如,假设用户 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;
则 psql 的\dp 命令将显示:
=> \dp mytable
Access privileges
Schema | Name | Type | Access privileges | Column privileges | Policies
--------+---------+-------+------------------------+-----------------------+----------
public | mytable | table | miriam=arwdDxtm/miriam+| col1: +|
| | | =r/miriam +| miriam_rw=rw/miriam |
| | | admin=arw/miriam | |
(1 row)
如果某个对象的“Access privileges”列为空,表示该对象具有默认权限(也就是说,它在相关系统目录中的权限条目为 null)。默认权限始终包括所有者的全部权限,并且根据对象类型的不同,还可能包括授予 PUBLIC 的一些权限,如上所述。对象上的第一个 GRANT 或 REVOKE 将实例化默认权限(例如生成 miriam=arwdDxt/miriam),然后再根据指定的请求修改它们。类似地,只有具有非默认权限的列才会在“Column privileges”中显示条目。(注意:这里的“默认权限”始终是指该对象类型的内置默认权限。受 ALTER DEFAULT PRIVILEGES 命令影响的对象,总会显示一个显式权限条目,其中包含 ALTER 的影响。)
注意所有者的隐式授予选项没有在访问权限显示中标记。仅当授予选项被显式授予给某人时才会出现*。
当对象的权限条目不为 null 但为空集合时,“Access privileges”列会显示(none)。这意味着根本没有授予任何权限,甚至连对象所有者也没有,这是一种很少见的情况。(在这种情况下,所有者仍然拥有隐式的授予选项,因此仍然可以重新授予自己的权限;只是当前并不持有这些权限。)
报告文档问题
阅读 上游文档. 通过 PostgreSQL 文档反馈表单.