将用户组合起来简化权限管理通常很方便:这样,权限可以授予或撤销整个组。PostgreSQL 中,这可以通过创建表示组的角色,然后向单个用户角色授予组角色中的成员资格来完成。
要设置组角色,首先创建该角色
CREATE ROLE name
;
通常情况下,作为组使用的角色不应使用 LOGIN
属性,但如果你愿意,也可以设置它。
一旦组角色存在,就可以使用 GRANT
和 REVOKE
命令添加和删除成员
GRANTgroup_role
TOrole1
, ... ; REVOKEgroup_role
FROMrole1
, ... ;
还可以授予其他组角色的成员资格(因为组角色和非组角色之间根本没有区别)。数据库不会允许你设置循环成员资格循环。此外,不允许授予 PUBLIC
角色中的成员资格。
组角色的成员可以通过两种方式使用角色的特权。首先,已使用 SET
选项授予成员资格的成员角色可以执行 SET ROLE
以暂时 “成为” 组角色。在这种状态下,数据库会话可以访问组角色的特权,而不是原始登录角色的特权,并且所创建的任何数据库对象都视为由组角色所有,而不是登录角色所有。其次,已使用 INHERIT
选项授予成员资格的成员角色可以自动使用那些直接或间接是成员的特权,但链条会在缺乏继承选项的成员资格处停止。举例来说,假设我们已完成
CREATE ROLE joe LOGIN; CREATE ROLE admin; CREATE ROLE wheel; CREATE ROLE island; GRANT admin TO joe WITH INHERIT TRUE; GRANT wheel TO admin WITH INHERIT FALSE; GRANT island TO joe WITH INHERIT TRUE, SET FALSE;
在以角色 joe
连接之后,数据库会话将使用直接授予 joe
以及授予 admin
和 island
的任何特权,因为 joe
“继承” 这些特权。但是,已授予 wheel
的特权不可用,因为即使 joe
间接是 wheel
的成员,成员资格是通过使用 WITH INHERIT FALSE
授予的 admin
。在之后
SET ROLE admin;
会话将只能使用授予 admin
的特权,而不是授予 joe
或 island
的特权。在之后
SET ROLE wheel;
会话将只能使用授予 wheel
的特权,而不是授予 joe
或 admin
的特权。可以恢复原始特权状态,方法是使用以下任何一种
SET ROLE joe; SET ROLE NONE; RESET ROLE;
SET ROLE
命令始终允许选择原始登录角色直接或间接隶属的任何角色,前提是存在一条成员资格授予链,每条链都具有 SET TRUE
(这是默认值)。因此,在上例中,在成为 wheel
之前无需成为 admin
。另一方面,根本无法成为 island
;joe
只能通过继承来访问那些特权。
在 SQL 标准中,用户和角色之间存在明显区别,并且用户不会自动继承特权,而角色会。这种行为可以在 PostgreSQL 中获得,方法是为用作 SQL 角色的角色赋予 INHERIT
属性,而为用作 SQL 用户的角色赋予 NOINHERIT
属性。但是,PostgreSQL 默认给予所有角色 INHERIT
属性,以向后兼容在用户始终可以使用授予其成员身份所在组的权限的 8.1 之前的版本。
角色属性 LOGIN
、SUPERUSER
、CREATEDB
和 CREATEROLE
可以被视作特殊特权,但它们永远不会像数据库对象上的普通特权一样被继承。您必须实际 SET ROLE
为具有其中一个属性的特定角色,以便使用该属性。继续上面的示例,我们可能会选择授予 CREATEDB
和 CREATEROLE
给 admin
角色。然后,以 joe
角色连接的会话不会立即拥有这些特权,只有在执行 SET ROLE admin
后才有这些特权。
若要销毁组角色,请使用 DROP ROLE
DROP ROLE name
;
组角色中的任何成员资格将自动被撤销(但成员角色不会受到其他影响)。