Postgresql 中文操作指南

22.3. Role Membership #

通常,将用户分组以减轻对权限的管理很方便:这样,权限可以授予或从一个整体组收回。在 PostgreSQL 中,这是通过创建一个表示该组的角色,然后授予 membership 组角色中的各个用户角色来完成的。

要设置一个组角色,首先创建角色:

CREATE ROLE name;

通常作为组使用的角色不会具有 LOGIN 属性,不过如果你愿意,可以设置它。

一旦组角色存在,您可以使用 GRANTREVOKE 命令添加和删除成员:

GRANT group_role TO role1, ... ;
REVOKE group_role FROM role1, ... ;

你也可以向其他组角色授予成员资格(因为组角色与非组角色之间实际上没有任何区别)。数据库不会允许你设置循环成员资格循环。此外,不允许向 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 的权限,外加授予 adminisland 的任何权限,因为 joe “继承”了这些权限。但是,授予 wheel 的权限不可用,因为即使 joe 间接是 wheel 的成员,成员资格也是通过 admin 获得的,而 admin 是使用 WITH INHERIT FALSE 授予的。在:

SET ROLE admin;

之后,会话将只能使用授予 admin 的那些权限,而不能使用授予 joeisland 的那些权限。在:

SET ROLE wheel;

之后,会话将只能使用授予 wheel 的那些权限,而不能使用授予 joeadmin 的那些权限。原始权限状态可用以下任何方式还原:

SET ROLE joe;
SET ROLE NONE;
RESET ROLE;

Note

SET ROLE 命令始终允许选择原始登录角色直接或间接成为其成员的任何角色,前提是有一个成员资格授予链,每个链都有 SET TRUE(这是默认设置)。因此,在上述示例中,在成为 wheel 之前,无需成为 admin。另一方面,根本无法成为 islandjoe 只可以通过继承访问这些特权。

Note

在 SQL 标准中,用户和角色之间有明显区别,用户不会自动继承特权,而角色会自动继承特权。通过向用作 SQL 角色的角色赋予 INHERIT 属性,同时向用作 SQL 用户的角色赋予 NOINHERIT 属性,可以在 PostgreSQL 中获得这种行为。但是,出于与 8.1 之前的版本(其中用户始终可以使用授予其所在组的权限)向后兼容的目的,PostgreSQL 默认将 INHERIT 属性赋予所有角色。

角色属性 LOGINSUPERUSERCREATEDBCREATEROLE 可以视为特殊权限,但它们从不会像普通权限那样继承数据库对象。你必须实际对具有其中一个属性的特定角色执行 SET ROLE 才能使用该属性。继续上面的示例,我们可以选择向 admin 角色授予 CREATEDBCREATEROLE。然后,以 joe 为角色连接的会话将不会立即拥有这些权限,而只有在执行 SET ROLE admin 之后才会有。

要销毁组角色,请使用 DROP ROLE

DROP ROLE name;

组角色的任何成员资格都会自动被撤销(但成员角色不会受到其他影响)。