PostgreSQL / 身份验证和授权
管理PostgreSQL中的角色和角色属性
简介
PostgreSQL使用各种机制在数据库集群中实现身份验证、授权和对象所有权。其中核心是角色的概念。
PostgreSQL角色是将用户和组的概念组合成一个单一、灵活的实体。它们是用户在数据库系统中的身份,是身份验证系统接受或拒绝连接的实体,也是所有范围权限管理规则的主体。
本指南将介绍什么是角色以及如何在PostgreSQL数据库集群中管理它们。更具体地说,本指南将涵盖与角色属性相关的角色管理。有关角色如何融入更大图景的更广泛概述,请参阅身份验证和授权简介指南。要了解如何更改特定数据库对象上的角色权限,请查看我们关于角色授权的指南。
什么是角色?
在PostgreSQL中,角色是特定能力、权限和“拥有”实体的分组。PostgreSQL不使用“用户”和“组”的独立概念,而是使用角色来表示这两个概念。一个角色可以对应现实世界中的一个人,或者它可以作为一个具有特定访问权限的组,其他角色可以成为其成员。
角色是PostgreSQL中确定身份验证和授权策略适用于谁的锚点。任何不普遍适用的策略都需要身份概念来定义限制谁和允许谁。在PostgreSQL中,此身份由角色表示。
PostgreSQL的身份验证系统有许多不同的组件,每个组件都与角色绑定。为了用于与数据库集群的初始连接,角色必须首先设置LOGIN
属性。身份验证规则本身定义在名为pg_hba.conf
的基于主机的配置文件中。每个规则定义可以作用于单个角色的身份验证方法。对于配置为密码身份验证的角色,必须设置密码属性,以便系统可以验证提供的用户密码。
在授权方面,角色在数据库集群级别定义,这意味着它们在PostgreSQL中是数据库之间共享的。由于角色跨越多个数据库,授权系统控制每个角色对每个数据库实体的访问级别。因为角色可以代表人群,所以在配置访问方面有很大的灵活性。
角色对于PostgreSQL中的对象所有权概念也至关重要。例如,每个数据库和表都只有一个角色被配置为所有者。除了超级用户
之外,所有者角色是唯一可以修改或删除实际对象的角色。
总而言之,角色是大多数实际数据库操作的核心。它们的灵活性使其既可以充当用户标识符,也可以充当用户类别。数据库集群中的每个操作都根据角色的权限进行检查,每次连接到数据库集群的成功都由进行身份验证的角色决定。由于角色管理在许多核心操作中都非常重要,因此掌握角色管理至关重要。
角色属性
角色属性是角色本身的标志,它们决定了角色在数据库集群级别的一些核心权限。这些属性可以在角色最初创建时设置,也可以由具有适当属性(本例中为SUPERUSER
或CREATEROLE
)的任何角色随时更改。
可以应用于角色的属性包括:
LOGIN
:允许用户使用此角色初步连接到数据库集群。CREATE USER
命令会自动添加此属性,而CREATE ROLE
命令则不会。SUPERUSER
:允许角色绕过所有权限检查,除了登录权限。只有其他SUPERUSER
角色才能创建具有此属性的角色。CREATEDB
:允许角色创建新数据库。CREATEROLE
:允许角色创建、更改和删除其他角色。此属性还允许角色分配或更改角色成员资格。例外情况是,具有CREATEROLE
属性的角色不能在不同时拥有SUPERUSER
属性的情况下更改SUPERUSER
角色。REPLICATION
:允许角色启动流复制。具有此属性的角色也必须具有LOGIN
属性。PASSWORD
:为角色分配一个密码,该密码将用于password
或md5
身份验证机制。此属性在属性关键字之后直接接受带引号的密码作为参数。INHERIT
:确定角色是否继承其所属角色的权限。如果没有INHERIT
属性,成员必须使用SET ROLE
更改为其他角色才能访问那些独占权限。此属性默认设置为新角色。
您可以通过查阅PostgreSQL关于角色属性和CREATE ROLE
命令的文档来了解更多关于角色属性的信息。
什么是superuser
角色?
如上文简要提及,一种特殊的权限称为superuser
,它允许对数据库集群进行无限制的管理员访问。这类似于Linux和Unix-like操作系统中的root
账户,但在数据库层面。
每个数据库集群中必须始终至少有一个具有superuser
权限的角色。初始的superuser
账户是在安装过程中创建的。初始superuser
账户的名称可能因安装过程而异,但最常见的是,此账户名为postgres
。
不建议使用具有superuser
权限的账户进行日常工作,这既是因为它可能执行破坏性操作,也是为了最大程度地减少泄露具有广泛访问权限的账户的可能性。相反,大多数时候,用户应该使用专用于其正在处理的特定功能或数据对象的账户,仅在需要更强大访问权限时才使用superuser
账户。
检查现有角色属性
现在您对角色属性以及它们允许的权限类型有了大致的了解,您应该学习如何在PostgreSQL中查找应用于角色的属性。本节将向您展示一些命令,帮助您查找一般角色和您自己当前角色上设置的属性。
列出所有数据库角色及其属性
有几种不同的方法可以检查应用于整个系统中的角色的属性。
如果您正在使用psql
命令行客户端,您可以利用一些有用的元命令,它们允许您无需查询即可获取角色属性信息。
\du
元命令显示所有角色及其属性
\du
List of rolesRole name | Attributes | Member of-----------+------------------------------------------------------------+-----------postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
在这种情况下,postgres
角色是为此数据库集群配置的具有superuser
权限的默认角色。
列出角色的等效SQL(通过在启动psql
时传递-E
或--echo-hidden
标志可发现)是
SELECT r.rolname, r.rolsuper, r.rolinherit,r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,r.rolconnlimit, r.rolvaliduntil,ARRAY(SELECT b.rolnameFROM pg_catalog.pg_auth_members mJOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)WHERE m.member = r.oid) as memberof, r.rolreplication, r.rolbypassrlsFROM pg_catalog.pg_roles rWHERE r.rolname !~ '^pg_'ORDER BY 1;
一个提供角色属性信息(不包括角色成员组件)的类似查询如下。我们在这里使用psql
元命令\x on
来垂直输出结果,以便更好地可读性
-- turn on vertical display\x onSELECT * FROM pg_roles WHERE rolname !~ '^pg_';-- turn off vertical display\x off
-[ RECORD 1 ]--+---------rolname | postgresrolsuper | trolinherit | trolcreaterole | trolcreatedb | trolcanlogin | trolreplication | trolconnlimit | -1rolpassword | ********rolvaliduntil |rolbypassrls | trolconfig |oid | 10
如果您只对查看哪些角色具有superuser
属性感兴趣,可以明确请求列表
SELECT rolname FROM pg_roles WHERE rolsuper;
rolname----------postgres(1 row)
或者,您可以列出所有用户及其superuser
状态,以获得更完整的视图
SELECT usename,usesuper FROM pg_user;
usename | usesuper----------+----------postgres | tuser1 | f(2 rows)
使用PostgreSQL的“角色”范式而不是其(有时模糊的)“用户”覆盖,可以使用这个稍微长一点的查询来检索相同的信息
SELECT rolname,rolsuper FROM pg_roles WHERE rolname !~ '^pg_';
rolname | rolsuper----------+----------postgres | tuser1 | f(2 rows)
列出您自己的属性
如果您想查找您当前使用的角色的属性,您可以轻松地过滤输出。
在使用psql
元命令时,您可以使用USER
变量,该变量将替换为当前连接的角色。psql
使用冒号(:
)来插入变量
\du :USER
List of rolesRole name | Attributes | Member of-----------+------------------------------------------------------------+-----------postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
要获取显示所有可能角色属性值的列表,您可以使用将角色名与PostgreSQL函数CURRENT_ROLE
返回的值进行比较的查询。同样,我们使用垂直输出以提高可读性
-- First, turn on vertical output\x onSELECT * FROM pg_roles WHERE rolename = CURRENT_ROLE;-- Change back to normal output\x off
-[ RECORD 1 ]--+---------rolname | postgresrolsuper | trolinherit | trolcreaterole | trolcreatedb | trolcanlogin | trolreplication | trolconnlimit | -1rolpassword | ********rolvaliduntil |rolbypassrls | trolconfig |oid | 10
要检查您当前的角色是否具有superuser
权限,您可以键入
SHOW is_superuser;
is_superuser--------------on(1 row)
检查您是否具有角色管理权限
要创建、更改或删除角色,您必须拥有superuser
或CREATEROLE
权限。
要检查系统中哪些角色具有角色管理权限,请键入
SELECT rolname as "Users who can manage roles" FROM pg_roles WHERE rolsuper OR rolcreaterole;
Users who can manage roles----------------------------postgres(1 rows)
如果您只想知道您当前的角色是否具有角色管理权限,您可以改为使用
SELECT 'Yes' AS "Can I manage roles?" FROM pg_roles WHERE rolname = :'USER' AND (rolsuper OR rolcreaterole);
Can I manage roles?---------------------Yes(1 row)
创建角色
验证您拥有角色管理权限后,您可以开始在PostgreSQL中创建、修改或删除角色。
设置角色属性的一种选择是在创建角色时声明它们。这允许您为角色设置初始条件,但如果需要更改角色的访问级别,您仍然可以在之后修改它们。您可以通过查阅CREATE ROLE
命令来熟悉基本语法。
创建角色的一种方法是使用命令行。PostgreSQL包含一个createuser
命令,它将在数据库集群中创建一个具有LOGIN
权限的角色。
通用语法是
createuser <options> <rolename>
例如,要创建一个名为admin
的具有superuser
权限的角色,并在提示时输入密码,您可以键入
createuser --superuser admin
然后,您将能够根据pg_hba.conf
文件中概述的身份验证方法,使用admin
账户登录。
要使用SQL
创建角色,通用语法如下
CREATE ROLE <role>;
属性可以通过在角色名后使用WITH
来指定
CREATE ROLE <role> WITH <options>;
例如,要创建一个名为user1
的角色,可以使用密码secretpassword
登录,您可以键入
CREATE ROLE "user1" WITH LOGIN PASSWORD 'secretpassword';
如果要创建一个具有superuser
权限(您也必须是superuser
才能成功执行此命令)且不能登录(用户必须使用SET ROLE
更改为此角色)的角色,您可以键入
CREATE ROLE "user2" WITH SUPERUSER;
更改现有角色
要修改现有角色的属性,您可以使用ALTER ROLE
命令。与角色创建一样,您当前的角色也必须具有superuser
或CREATEROLE
权限。没有这些权限的用户只能使用ALTER ROLE
命令更改自己的密码。
更改角色允许您在创建后更改分配给角色的属性。ALTER ROLE
语法可以使用角色创建部分中提到的相同属性。一个区别是每个属性类型都可以通过添加NO
前缀来否定。例如,要允许角色登录到数据库集群,可以为其赋予LOGIN
属性。要删除该功能,您可以通过指定NOLOGIN
来更改角色。
ALTER ROLE
命令只更改那些明确提及的属性。换句话说,ALTER ROLE
命令指定属性的更改,而不是一组全新的属性。
要允许user2
角色登录到数据库集群,您可以键入
ALTER ROLE "user2" WITH LOGIN;
请记住,虽然这启用了登录功能,但允许的身份验证方法仍由pg_hba.conf
文件控制。
如果您希望user2
能够登录、创建角色和创建数据库,您可以指定这三个属性,用空格分隔
ALTER ROLE "user2" WITH LOGIN CREATEROLE CREATEDB;
要撤销角色的superuser
状态(您只能使用另一个superuser
角色执行此命令),请键入
ALTER ROLE "user2" WITH NOSUPERUSER;
要更改角色的密码,您可以键入以下内容(所有角色都应该能够在自己的角色上执行此命令,无论是否具有CREATEROLE
或superuser
权限)
ALTER ROLE <role> WITH PASSWORD '<password>';
尽管上述命令有效,但如果可能,最好使用psql
元命令来更改密码。psql
命令会自动提示输入密码并在将其发送到服务器之前对其进行加密。这有助于避免敏感数据泄露到日志中。
您可以通过键入以下内容来使用psql
更改角色的密码
-- To change your own password\password-- To change the password for another role\password <role>
您还可以使用ALTER ROLE
命令重命名角色
ALTER ROLE <role> RENAME TO <newrole>
请记住,您无法重命名当前会话角色。
删除角色
删除现有角色遵循与之前命令类似的模式。同样,您必须具有CREATEROLE
或superuser
权限才能执行这些命令。
一个复杂因素是,如果角色仍然被数据库中的对象引用,则不能删除它们。这意味着您必须删除或转移角色拥有的任何对象的所有权。之后,您还必须撤销角色对数据库对象的任何额外权限。
Erwin Brandstetter在Database Administrators Stack Exchange网站上提供了关于如何适当重新分配和删除权限的详细解释。以下使用相同的过程。
首先,您可以使用REASSIGNED OWNED
命令重新分配角色的所有自有对象。例如,如果您准备删除user2
角色,您可以将其对象分配给postgres
角色,方法是键入
REASSIGN OWNED BY "user2" TO "postgres";
现在对象归postgres
所有,我们可以使用DROP OWNED
命令撤销我们被授予的所有其他对象权限。此命令还会删除我们拥有的任何对象,但由于我们刚刚将它们转移给了postgres
角色,因此user2
角色不再拥有任何对象。因此,该命令只会撤销角色的任何额外权限
DROP OWNED BY "user2";
如果没有上面的DROP OWNED
快捷方式,您将不得不对角色拥有权限的每个单独对象或对象类型执行REVOKE ALL PRIVILEGES
。
撤销所有相关权限后,您可以键入以下内容来删除角色
DROP ROLE "user2";
使用psql
登录
一旦您配置了新角色,并使用pg_hba.conf
文件配置了身份验证详细信息,您就可以使用新角色登录到数据库集群。psql
命令行客户端提供了一种简单的方法来执行此操作。
默认情况下,psql
假定您希望使用与您的操作系统用户名匹配的角色进行连接。因此,如果您以john
身份登录计算机,psql
将假定您希望尝试使用也名为john
的角色连接到数据库。
要覆盖此行为,您可以传递-U
或--username=
选项。例如,如果您想登录到名为kerry
的角色,您可以键入
psql -U kerry
psql
命令的成功将取决于kerry
角色的存在、您尝试连接的服务器的可访问性以及服务器上定义的身份验证规则。
会话期间切换到不同角色
有时,您可能希望暂时采用您有权访问的另一个角色的权限和身份。例如,如果您的当前角色没有INHERIT
属性,而您想获得您作为其成员的某个角色的权限,则这是必需的。
要了解其工作原理,您必须了解PostgreSQL用于分类活动角色的术语
- 会话角色:会话角色是您在首次连接到PostgreSQL数据库集群时登录的角色。它设置您的初始权限并确定您对系统的访问权限。此角色必须具有
LOGIN
属性。 - 当前角色:相比之下,当前角色是您当前扮演的角色。与当前角色关联的权限,无论是直接设置还是从其他角色继承,都决定了您允许执行的操作以及您可以访问的对象。
您可以通过键入以下内容来查看会话和当前角色值
SELECT SESSION_USER, CURRENT_USER;
current_user | session_user--------------+--------------postgres | postgres(1 row)
虽然更改会话角色的唯一方法是使用不同角色启动新连接,但您可以使用SET ROLE
命令更改当前角色。SET ROLE
命令用于暂时扮演不同角色。该命令还可以选择以下修饰符
SESSION
:默认设置。这会使SET ROLE
命令影响整个数据库会话。LOCAL
:此修饰符将使命令仅更改当前事务的角色。
要将当前角色更改为user2
角色(对于会话的其余部分),请键入
SET ROLE "user2";
如果您检查您的会话和当前角色值,您将看到当前角色值已更改
SELECT SESSION_USER, CURRENT_USER;
current_user | session_user--------------+--------------user2 | postgres(1 row)
您所有的操作现在都将使用user2
角色作为其上下文。
要切换回您之前使用的会话角色,您可以键入
SET ROLE NONE;
另一种实现相同结果的方法是
RESET ROLE;
结论
PostgreSQL的角色、角色属性、授权和身份验证系统创建了一个灵活的系统,允许管理员有效地管理权限和数据库访问。本指南描述了角色究竟是什么以及它们如何涵盖广泛的用例。它还涵盖了如何创建、修改和删除角色以及管理决定其全局功能的角色属性。了解如何管理这些身份对于保护您的数据库并为合法用户提供可用访问至关重要。
常见问题
要在PostgreSQL中更改角色的密码,您可以使用带有PASSWORD
的ALTER
语句。语法如下
ALTER ROLE <role> WITH PASSWORD '<password>';
或者,您也可以使用psql
元命令,如下所示
- To change your own password\password-- To change the password for another role\password <role>
要查找当前角色的属性,您可以使用带有USER
变量的psql
元命令,该变量将替换为当前连接的角色。
基本语法和结果如下
\du :USER
List of rolesRole name | Attributes | Member of-----------+------------------------------------------------------------+-----------postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
要检查角色是否可以授予用户权限或创建角色,您可以使用以下SQL语句
SELECT rolname as "Users who can manage roles" FROM pg_roles WHERE rolsuper OR rolcreaterole;
要检查您的用户是否拥有这些权限,您可以使用以下语句
SELECT 'Yes' AS "Can I manage roles?" FROM pg_roles WHERE rolname = :'USER' AND (rolsuper OR rolcreaterole);
REPLICATION
是PostgreSQL中的一个角色属性,它允许该角色启动流式复制。
具有此属性的角色也必须具有LOGIN
属性。
您可以通过使用CREATE ROLE
命令在PostgreSQL中创建角色。
基本语法如下
CREATE ROLE <role>;
带有属性的语法如下
CREATE ROLE <role> WITH <options>;