前面几章分别介绍了服务程序的安装、管理、登录、密码修改等信息,后面的几章就开始深入学习数据库、表等数据库内部结构和信息管理。在学习数据库内部结构之前,我们先学习PostgreSQL里的权限管理,因为后面学习的数据库大部分操作都是和用户以及权限相关联的,只有把权限搞懂了,才能理解后面各种操作的含义。
角色/用户的定义和区别
角色(role)的定义
在PostgreSQL里,角色是用来进行数据库登录和管理的一个ID。有点像是linux上的用户和群组的综合体,具有这两者的功能。
比如我们定义了一个角色dba,用来管理数据库,那么既可以通过角色dba来登录数据库,进行数据库管理。还可以将其他角色添加到dba这个角色里来。让其他角色也具有管理数据库的功能,其他角色自动继承dba的权限。
后面讲到权限的时候,我们还会说到,角色dba对某张表具有全部权限的时候,他可以把部分权限分配给角色组里的其他成员,实现精细化控制。
用户的定义,以及和角色的区别
在PostgreSQL里,角色role和用户user是一样的概念,除了名称不一样。还有一点区别就是:创建用户默认具有登录(login)权限,而创建角色默认没有登录权限。
它们的命令用户也几乎是一模一样的。下面我们一起来看。
角色/用户的管理
PostgreSQL进行角色管理的基本原则是:将数据库的表或者视图的权限赋予给某个角色,然后再将这个用户添加到这个角色中,这个用户就自动拥有了这个角色的权限。当这个用户离职时,取消其角色即可,实现了权限和用户的灵活管理。
在实际的应用中,PostgreSQL中用户也可以当作角色使用,可以把用户赋予给另外一个用户。但是尽量不要这样使用。
角色/用户管理的基本命令有:
- 创建角色/用户
CREATE ROLE/USER
- 删除角色/用户
DROP ROLE/USER
- 修改角色/用户
ALTER ROLE/USER
下面我们依次来看这些命令的用法:
1. 创建角色和用户命令、删除用户和角色命令
创建角色的基本命令格式是:
CREATE ROLE/USER name [ [ with ] option [ ... ] ]
option 可以是下面的这些值:
- SUPERUSER | NOSUPERUSER
- CREATEDB | NOCREATEDB
- CREATEROLE | NOCREATEROLE
- CREATEUSER | NOCRATEUESR
- INHERIT | NO INHERIT
- LOGIN | NOLOGIN
- REPLICATION | NOREPLICATION
- BYPASSRLS | NOBYPASSRLS
- CONNECTION LIMIT connlimit
- [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'password'
- VALID UNTIL 'timestamp'
- IN ROLE role_name
- IN GROUP role_name
- ROLE role_name
- ADMIN role_name
- USER role_name
- SYSID uid
命令里的name指的是角色/用户的名称,后面的选项看起来很多,但是很多选项的意义是相同的,知道了其中一个的用法,另外的也知道怎么用了。
选项含义
-
SUPERUSER | NOSUPERUSER
,用来创建一个超级用户,要求创建者自己是超级用户。超级用户拥有数据库的所有权限,因此小心使用这个选项。默认是NOSUPERUSER
-
CREATEDB | NOCREATEDB
让角色拥有创建数据库的权限,默认值是NOCREATEDB
-
CREATEROLE | NOCREATEROLE
让角色有创建新角色的权限,但是新角色拥有的最大权限也不会超过它的父角色的权限。默认是NOCREATEROLE
-
CREAETEUSER | NOCREATEUSER
即将废弃的选项,允许角色创建新用户,但是这个选项和CREATEROLE | NOCREATEROLE
选项并不是对等的,区别我们在后面的示例中看。 -
INHERIT | NOINHERIT
用来确定这个角色是否继承它的父角色的权限,默认是INHERIT
-
LOGIN | NOLOGIN
是否允许角色登录,如果角色创建时带上了LOGIN选项,那么相当于是CREATE USER
,角色这个选项的默认值是NOLOGIN
。 -
REPLICATION | NO REPLICATION
用来允许角色初始化流复制或者将系统转换为备份模式。拥有这个选项的角色权限比较高,因此只能用于特定角色上面。默认是NOREPLICATION
-
BYPASSRLS | NOBYPASSRLS
这个选项决定角色是否绕过每个行级安全策略(RLS),默认是NOBYPASSRLS。PostgreSQL数据库里的表默认是行级安全的,默认情况下只有超级用户和表的拥有者会绕过RLS。因此如果你给某个角色在某个表上有BYPASSRLS
权限,那么它能够通过pg_dump命令将数据库备份出去。 -
CONNECTION LIMIT connlimit
设置这个角色的连接数限制 -
ENCRYPTED | UNENCRYPTED
控制角色密码在系统表里是否加密存储,默认值是通过配置文件里的password_encryption
设置的,默认值是on
,即加密。如果密码在存储数据库的时候已经是加密以后的密文,那么无论是否设置这个选项都无所谓。因为PostgreSQL无法解出密码。 -
PASSWORD password
设置角色的密码,如果你不想这个角色可以通过认证,可以将密码设置为NULL
,这样任何情况下都会认证失败。 -
VALID UNTIL 'timestamp'
设置角色密码的过期时间,不设置的话,角色密码一直有效。 -
IN ROLE role_name
要将创建的新角色name
添加到角色role_name
里面去,可以跟多个role_name的名称 -
IN GROUP role_name
和IN ROLE
一个意思 -
ROLE role_name
将role_name
添加到新创建的角色name里面去,注意,这个选项和 IN ROLE选项的意思刚好相反 -
ADMIN role_name
也是将role_name
添加到新创建的角色name
里面去,但是role_name
在新的角色里拥有添加新角色的权限。相当于把role_name
设置为群组管理员,可以管理群里的用户。 -
USER role_name
和ROLE role_name
的用法一样 -
SYSID uid
手动设置角色的ID,默认是自动分配。
如果选项全都不带的话,那么就会使用这些选项的默认值。看完了创建的命令,我们再看看删除用户和角色的命令,删除用户和角色的命令相比较之下就非常简单了。如下所示,基本命令格式是:
DROP ROLE/USER [ IF EXIST ] name [,....]
选项含义:
-
IF EXISTS
可选的选项,用于角色或用户不存在的情况,不带这个参数时,删除不存在的用户会报错。带这个参数时不会报错,但是会给出提示信息。 - name 角色或用户的名称
选项含义详解示例
LOGIN | NOLOGIN、PASSWORD
下面我们先从简单的选项开始看起,先看LOING | NOLOGIN
、PASSWORD
这两个选项(当前以postgres这个超级用户登录和操作):
postgres=# create role dba1; #创建一个角色dba
CREATE ROLE
postgres=# create user dba2; #创建一个用户dba2
CREATE ROLE
从上面可以看到,创建role和user的时候,提示都是创建角色。但是创建的role和user有什么区别呢?我们来看一下:
postgres=# \password dba1; #修改dba1的密码
Enter new password:
Enter it again:
postgres=# \password dba2; #修改用户dba2的密码
Enter new password:
Enter it again:
postgres=# \q # 退出postgres用户
[root@cephadmin ~]# psql -U dba1 #尝试使用dba1登录
Password for user dba1:
psql: FATAL: role "dba1" is not permitted to log in #这里提示角色dba1不允许登录
[root@cephadmin ~]# psql -U dba2 #尝试使用dba2登录
Password for user dba2:
psql: FATAL: database "dba2" does not exist #没有提示不允许登录,但是提示数据库dba2不存在。
从上面可以看到,通过create role创建的角色是不允许登录的,这是因为CREATE ROLE命令其中一个默认值是NOLOGIN,不能登录。而CREATE USER命令创建的角色则是LOGIN,即可登录。只是因为没有给dba2配置默认的数据库,所以登录出错。我们配置好dba2的数据库看一下:
postgres=# create database dba2; #切换回postgres用户,创建数据库dba2
CREATE DATABASE
postgres=# \q
[root@cephadmin ~]# psql -U dba2 #使用dba2用户登录。
Password for user dba2:
psql (9.6.6)
Type "help" for help.
dba2=> \l
可以看到此时正常登录,从这里就能看到LOGIN和NOLOGIN
的区别。再看一个验证示例:
postgres=# CREATE ROLE dba3 LOGIN PASSWORD '123456';
CREATE ROLE
postgres=# CREATE ROLE dba4 NOLOGIN PASSWORD '123456';
CREATE ROLE
postgres=# \q
-bash-4.2$ psql -p 5433 -U dba3
Password for user dba3:
psql: FATAL: database "dba3" does not exist
-bash-4.2$ psql -p 5433 -U dba4
Password for user dba4:
psql: FATAL: role "dba4" is not permitted to log in
这里我们在创建的时候直接带上了LOGIN
和NOLOGIN
这两个选项,同时还直接使用PASSWORD
这个选项给角色创建初始密码。从尝试登录的结果可以看到,这个时候角色dba3可以登录,而用户dba4不能登录,和上面那个示例刚好是反的,进一步验证了这两个选项的功能。
创建的示例我们看完了,再看下删除用户的示例:
postgres=# drop role dba1;
DROP ROLE
postgres=# drop role if exists dba1;
NOTICE: role "dba1" does not exist, skipping
DROP ROLE
postgres=# drop role dba1;
ERROR: role "dba1" does not exist
postgres=# drop role dba2;
DROP ROLE
postgres=# drop user dba3;
DROP ROLE
postgres=# drop user dba4;
DROP ROLE
上面的几个删除操作把删除角色/用户的几个操作都涉及到了。我们分别来看一下:
- 第一个使用DROP ROLE命令删除角色dba1,成功
- 第二个使用DROP ROLE IF EXISTS命令删除角色dba1,因为已经删除过,但是又IF EXISTS子句,所以给出NOTICE
- 第三个使用DROP ROLE命令删除角色dba1,因为已经删除过,且没有IF EXISTS判断,所以给出错误ERROR
- 第四个使用DROP ROLE命令删除用户dba2,成功,可以看到用户和角色没有区别
- 第五个使用DROP USER命令删除角色dba3,成功,同样说明用户和角色没有区别
- 第六个使用DROP USER命令删除用户dba4,成功。
SUPERUSER、CREATEDB、CREATEROLE
我们再接着看和数据库、表以及角色相关的选项,如下所示:
- SUPERUSER | NOSUPERUSER —— 超级用户
- CREATEDB | NOCREATED —— 拥有创建数据库的权限
- CREATEROLE | NOCREATEROLE —— 拥有管理其他角色的权限
这些权限都可以在创建角色时,附加到对应的角色上面。我们从最简单的示例开始,依次创建各个等级的角色
- 创建可管理其他角色的角色。
#创建一个角色dba2,带上CRATE ROLE 和 LOGIN选项
postgres=# create role dba2 createrole login password '123456';
CREATE ROLE
postgres=# \q
#使用dba2这个角色登录,可以成功登录。
[root@cephadmin ~]# psql -U dba2
Password for user dba2:
psql (9.6.6)
Type "help" for help.
#使用dba2这个角色创建新的角色dba22,并设置账号密码
dba2=> create role dba22 login password '123456';
CREATE ROLE
# 创建拥有createrole权限的角色dba23
dba2=> create role dba23 createrole login;
CREATE ROLE
#使用dba2这个角色创建dba22的数据库,提示权限不足。
dba2=> create database dba22;
ERROR: permission denied to create database
dba2=> \q
[root@cephadmin ~]# psql -U dba22
Password for user dba22:
psql: FATAL: database "dba22" does not exist
#删除创建的两个子角色
dba2=> drop role dba22;
DROP ROLE
dba2=> drop role dba23;
DROP ROLE
从上面的示例中可以总结如下,具有createrole
权限的角色:
- 可以创建新的角色(例如dba22)
- 同时也创建具有createrole权限角色(例如dba23)
- 但是不能为自己创建的子角色创建数据库(例如无法创建数据库dba22)
- 可以删除自己创建的子角色。
- 创建具有
createdb
权限的角色
#创建具有createdb权限的角色dba3
postgres=# create role dba3 createdb login password '123456';
CREATE ROLE
#为角色dba3创建数据库dba3
postgres=# create database dba3;
CREATE DATABASE
postgres=# \q
#使用角色dba3登录,可以正常登录
[root@cephadmin ~]# psql -U dba3;
Password for user dba3:
psql (9.6.6)
Type "help" for help.
#在角色dba3下尝试创建其他角色,提示操作被拒绝
dba3=> create role dba33 createrole login password '123456';
ERROR: permission denied to create role
dba3=> create role dba33 login password '123456';
ERROR: permission denied to create role
#尝试创建数据库dba33,创建成功
dba3=> create database dba33;
CREATE DATABASE
dba3=> \l dba33;
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-------+-------+----------+-------------+-------------+-------------------
dba33 | dba3 | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
(1 row)
#删除创建的数据库dba33,删除成功。
dba3=> drop database dba33;
DROP DATABASE
dba3=> \q
从上面的示例中可以看出,具有createdb
权限的角色:
- 具有创建数据库的权限(例如创建数据库dba33)
- 没有创建角色的权限(例如无法创建子角色dba33)
综合上面两个示例,我们可以看到,如果我们想一个角色具有创建数据库以及创建角色的权限,那么它必须要同时拥有createdb
和createrole
这两个权限。
- 创建具有
superuser
选项的角色
superuser
角色是拥有超级权限的角色。默认情况下只有postgres用户拥有此权限。因此,当postgres设置其他角色为superuser后,也会具有postgres拥有的所有权限。因此这个权限一定要谨慎设置。
#创建一个超级用户角色dba4,设置为可登录,密码123456
postgres=# create role dba4 superuser login password '123456';
CREATE ROLE
#创建数据库dba4
postgres=# create database dba4;
CREATE DATABASE
postgres=# \q
#使用dba4角色登录
[root@cephadmin ~]# psql -U dba4
Password for user dba4:
psql (9.6.6)
Type "help" for help.
#使用dba4创建拥有createrole选项的角色dba44,设置密码为123456
dba4=# create role dba44 createrole password '123456';
CREATE ROLE
#使用dba4创建拥有createdb选项的角色dba45,设置密码为123456
dba4=# create role dba45 createdb password '123456';
CREATE ROLE
#创建数据库dba44
dba4=# create database dba44;
CREATE DATABASE
#创建数据库dba45
dba4=# create database dba45;
CREATE DATABASE
从上面的示例中可以看到:
- 超级用户具有上面几种角色的所有权限
到这里就说完了接近一半选项的作用,下面我们继续看。
IN ROLE/IN GROUP、ROLE/USER、ADMIN、INHERIT、VALID UNTIL、CONNECTION LIMIT、ENCRYPTED 、SYSID
最后这一段的要将的比较多,但是比较重要的还是前面几个。后面的VALID UNTIL、CONNECTION LIMMIT、ENCRYPTED、SYSID不是特别重要或者说使用的不是很多,可能就简单说明一下。
这里先说一下IN ROLE
、IN GROUP
、ROLE
、USER
这四个选项,前面两个作用是将新创建的角色添加到以有的某个角色中,同时新创建的角色会自动继承(INHERIT)已有的这个角色的所有权限,和INHERIT
这个选项紧密关联。后面连个关键字的作用是,将已有的角色添加到新创建的角色中,和前两个关键字作用相反,但是也是涉及到权限的继承问题,这里把它们放到一起讲。但是因为这里涉及到了权限的问题,那么我需要在后面权限的内容学习完了以后,再来讲这几个选项的作用,这样更便于理解。此外,ADMIN
这个选项也是和权限相关的,也放到后面讲。
那么我们剩下需要说的就只剩下VALID UNTIL、CONNECTION LIMIT 、ENCRYPTED、SYSID这四个选项了。
首先来说说VALID UNTIL,后面跟一个日期字符串,用来设置角色或者用户的密码过期日期,当服务器时间超过这个日期时,再登录就会提示密码错误,即使密码是对的也会提示。如果登录时认证方式设置的是trust,那么这个选项无效。如果不使用这个选项,那么默认密码一直有效。
CONNECTION LIMIT是用来设置角色可以创建的连接数,0表示禁止连接,-1表示不限制数量。其他数字表示对应的连接数。
ENCRYPTED表示给用户密码加密,而SYSID表示手动设置角色或用户的系统ID,这里也不过多赘述了。后面我们就开始看权限的内容,权限的知识了解完毕后,就结合权限知识把上面没有讲到的4个选项一起讲解一下。
2. 查看当前角色的命令有2个,分别是:
postgres=# \du
List of roles
Role name | Attributes | Member
of
-----------+------------------------------------------------------------+--------
dbuser | | {}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
postgres=# select rolname from pg_roles;
rolname
-------------------
pg_signal_backend
postgres
dbuser
(3 rows)
第一个\du
是psql的元命令,第二个是SQL语句。