暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL 角色用户管理

原创 huayumicheng 2023-01-01
595



一、角色与用户的区别

PostgreSQL使用角色的概念管理数据库访问权限。 根据角色自身的设置不同,一个角色可以看做是一个数据库用户,或者一组数据库用户。 角色可以拥有数据库对象(比如表)以及可以把这些对象上的权限赋予其它角色, 以控制谁拥有访问哪些对象的权限。

其实用户和角色都是角色,只是用户是具有登录权限的角色。

在PostgreSQL 里没有区分用户和角色的概念,"CREATE USER" 为 "CREATE ROLE" 的别名,这两个命令几乎是完全相同的,唯一的区别是"CREATE USER" 命令创建的用户默认带有LOGIN属性,而"CREATE ROLE" 命令创建的用户默认不带LOGIN属性(CREATE USER is equivalent to CREATE ROLE except that CREATE USER assumes LOGIN by default, while CREATE ROLE does not)。


1.1 创建角色与用户


CREATE ROLE 语法

CREATE ROLE name [ [ WITH ] option [ ... ] ]
where option can be:
      SUPERUSER | NOSUPERUSER
    | CREATEDB | NOCREATEDB
    | CREATEROLE | NOCREATEROLE
    | CREATEUSER | NOCREATEUSER
    | INHERIT | NOINHERIT
    | LOGIN | NOLOGIN
    | REPLICATION | NOREPLICATION
    | 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
复制


创建david 角色和sandy 用户

postgres=# CREATE ROLE david;  //默认不带LOGIN属性
CREATE ROLE
postgres=# CREATE USER sandy;  //默认具有LOGIN属性
CREATE ROLE
postgres=# \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 david     | Cannot login                                   | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 sandy     |                                                | {}

postgres=#
postgres=# SELECT rolname from pg_roles ;
 rolname 
----------
 postgres
 david
 sandy
(3 rows)
postgres=# SELECT usename from pg_user;         //角色david 创建时没有分配login权限,所以没有创建用户
 usename 
----------
 postgres
 sandy
(2 rows)

postgres=#
复制


1.2 验证LOGIN属性

postgres@CS-DEV:~> psql -U david
psql: FATAL:  role "david" is not permitted to log in
postgres@CS-DEV:~> psql -U sandy
psql: FATAL:  database "sandy" does not exist
postgres@CS-DEV:~> psql -U sandy -d postgres
psql (9.1.0)
Type "help" for help.

postgres=> \dt
No relations found.
postgres=>
复制

用户sandy 可以登录,角色david 不可以登录。


1.3 修改david 的权限,增加LOGIN权限

postgres=# ALTER ROLE david LOGIN ;
ALTER ROLE
postgres=# \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 david     |                                                | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 sandy     |                                                | {}

postgres=# SELECT rolname from pg_roles ;
 rolname 
----------
 postgres
 sandy
 david
(3 rows)
postgres=# SELECT usename from pg_user;  //给david 角色分配login权限,系统将自动创建同名用户david
 usename 
----------
 postgres
 sandy
 david
(3 rows)

postgres=#
复制

1.4 再次验证LOGIN属性

postgres@CS-DEV:~> psql -U david -d postgres
Type "help" for help.

postgres=> \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 david     |                                                | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 sandy     |                                                | {}

postgres=>
复制

david 现在也可以登录了。


二、查看角色信息


psql 终端可以用\du 或\du+ 查看,也可以查看系统表 select * from pg_roles;

postgres=> \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 david     | Cannot login                                   | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 sandy     |                                                | {}

postgres=> \du+
                                    List of roles
 Role name |                   Attributes                   | Member of | Description
-----------+------------------------------------------------+-----------+-------------
 david     | Cannot login                                   | {}        |
 postgres  | Superuser, Create role, Create DB, Replication | {}        |
 sandy     |                                                | {}        |

postgres=> SELECT * from pg_roles;
 rolname  | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcatupdate | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolconfig |  oid 
----------+----------+------------+---------------+-------------+--------------+-------------+----------------+--------------+-------------+---------------+-----------+-------
 postgres | t        | t          | t             | t           | t            | t           | t              |           -1 | ********    |               |           |    10
 david    | f        | t          | f             | f           | f            | f           | f              |           -1 | ********    |               |           | 49438
 sandy    | f        | t          | f             | f           | f            | t           | f              |           -1 | ********    |               |           | 49439
(3 rows)

postgres=>
复制


三、角色属性(Role Attributes)


一个数据库角色可以有一系列属性,这些属性定义了他的权限。


属性 说明

login只有具有 LOGIN 属性的角色可以用做数据库连接的初始角色名
superuser数据库超级用户
createdb创建数据库权限
createrole允许其创建或删除其他普通的用户角色(超级用户除外)
replication做流复制的时候用到的一个用户属性,一般单独设定。
password在登录时要求指定密码时才会起作用,比如md5或者password模式,跟客户端的连接认证方式有关
inherit用户组对组员的一个继承标志,成员可以继承用户组的权限特性


四、创建用户时赋予角色属性


从pg_roles 表里查看到的信息,在上面创建的david 用户时,默认没有创建数据库等权限。

postgres@CS-DEV:~> psql -U david -d postgres
Type "help" for help.

postgres=> \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------+-----------
david | | {}
postgres | Superuser, Create role, Create DB, Replication | {}
sandy | | {}

postgres=> CREATE DATABASE test;
ERROR: permission denied to create database
postgres=>
复制

如果要在创建角色时就赋予角色一些属性,可以使用下面的方法。

首先切换到postgres 用户。


4.1 创建角色bella 并赋予其CREATEDB 的权限。

postgres=# CREATE ROLE bella CREATEDB ;
CREATE ROLE
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------+-----------
bella | Create DB, Cannot login | {}
david | | {}
postgres | Superuser, Create role, Create DB, Replication | {}
sandy | | {}

postgres=#
复制


4.2 创建角色renee 并赋予其创建数据库及带有密码登录的属性。

postgres=# CREATE ROLE renee CREATEDB PASSWORD 'abc123' LOGIN;
CREATE ROLE
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------+-----------
bella | Create DB, Cannot login | {}
david | | {}
postgres | Superuser, Create role, Create DB, Replication | {}
renee | Create DB | {}
sandy | | {}

postgres=#
复制


4.3 测试renee 角色


a. 登录

postgres@CS-DEV:~> psql -U renee -d postgres
Type "help" for help.

postgres=>
复制

用renee 用户登录数据库,发现不需要输入密码既可登录,不符合实际情况。

b. 查找原因

在角色属性中关于password的说明,在登录时要求指定密码时才会起作用,比如md5或者password模式,跟客户端的连接认证方式有关。

查看pg_hba.conf 文件,发现local 的METHOD 为trust,所以不需要输入密码。

将local 的METHOD 更改为password,然后保存重启postgresql。


五、给已存在用户赋予各种权限


使用ALTER ROLE 命令。

ALTER ROLE 语法:
ALTER ROLE name [ [ WITH ] option [ ... ] ]
where option can be:

      SUPERUSER | NOSUPERUSER
    | CREATEDB | NOCREATEDB
    | CREATEROLE | NOCREATEROLE
    | CREATEUSER | NOCREATEUSER
    | INHERIT | NOINHERIT
    | LOGIN | NOLOGIN
    | REPLICATION | NOREPLICATION
    | CONNECTION LIMIT connlimit
    | [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'password'
    | VALID UNTIL 'timestamp'

ALTER ROLE name RENAME TO new_name

ALTER ROLE name [ IN DATABASE database_name ] SET configuration_parameter { TO | = } { value | DEFAULT }
ALTER ROLE name [ IN DATABASE database_name ] SET configuration_parameter FROM CURRENT
ALTER ROLE name [ IN DATABASE database_name ] RESET configuration_parameter
ALTER ROLE name [ IN DATABASE database_name ] RESET ALL
复制

5.1 赋予bella 登录权限

a. 查看现在的角色属性

postgres=# \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 bella     | Create DB, Cannot login                        | {}
 david     |                                                | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 renee     | Create DB                                      | {}
 sandy     |                                                | {}

postgres=#
复制

b. 赋予登录权限

postgres=# ALTER ROLE bella WITH LOGIN;
ALTER ROLE
postgres=# \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 bella     | Create DB                                      | {}
 david     |                                                | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 renee     | Create DB                                      | {}
 sandy     |                                                | {}

postgres=#
复制

5.2 赋予renee 创建角色的权限

postgres=# ALTER ROLE renee WITH CREATEROLE;
ALTER ROLE
postgres=# \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 bella     | Create DB                                      | {}
 david     |                                                | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 renee     | Create role, Create DB                         | {}
 sandy     |                                                | {}

postgres=#
复制

5.3 赋予david 带密码登录权限

postgres=# ALTER ROLE david WITH PASSWORD 'ufo456';
ALTER ROLE
postgres=#
复制

5.4 设置sandy 角色的有效期

postgres=# ALTER ROLE sandy VALID UNTIL '2019-04-24';
ALTER ROLE
postgres=# \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 bella     | Create DB                                      | {}
 david     |                                                | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 renee     | Create role, Create DB                         | {}
 sandy     |                                                | {}

postgres=# SELECT * from pg_roles ;
 rolname  | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcatupdate | rolcanlogin | rolreplication | rolconnlimit | rolpassword |     rolvaliduntil      | rolconfig |  oid 
----------+----------+------------+---------------+-------------+--------------+-------------+----------------+--------------+-------------+------------------------+-----------+-------
 postgres | t        | t          | t             | t           | t            | t           | t              |           -1 | ********    |                        |           |    10
 bella    | f        | t          | f             | t           | f            | t           | f              |           -1 | ********    |                        |           | 49440
 renee    | f        | t          | t             | t           | f            | t           | f              |           -1 | ********    |                        |           | 49442
 david    | f        | t          | f             | f           | f            | t           | f              |           -1 | ********    |                        |           | 49438
 sandy    | f        | t          | f             | f           | f            | t           | f              |           -1 | ********    | 2019-04-24 00:00:00+08 |           | 49439
(5 rows)

postgres=#
复制


六、角色赋权/角色成员


在系统的角色管理中,通常会把多个角色赋予一个组,这样在设置权限时只需给该组设置即可,撤销权限时也是从该组撤销。在PostgreSQL中,首先需要创建一个代表组的角色,之后再将该角色的membership 权限赋给独立的角色即可。

6.1 创建组角色

postgres=# CREATE ROLE father login nosuperuser nocreatedb nocreaterole noinherit encrypted password 'abc123';
CREATE ROLE
postgres=# \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 bella     | Create DB                                      | {}
 david     |                                                | {}
 father    | No inheritance                                 | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 renee     | Create role, Create DB                         | {}
 sandy     |                                                | {}

postgres=#
复制

6.2 给father 角色赋予数据库test 连接权限和相关表的查询权限。

postgres=# GRANT CONNECT ON DATABASE test to father;
GRANT
postgres=# \c test renee
You are now connected to database "test" as user "renee".
test=> \dt
No relations found.
test=> CREATE TABLE emp (
test(> id serial,
test(> name text);
NOTICE:  CREATE TABLE will create implicit sequence "emp_id_seq" for serial column "emp.id"
CREATE TABLE
test=> INSERT INTO emp (name) VALUES ('david'); 
INSERT 0 1
test=> INSERT INTO emp (name) VALUES ('sandy');
INSERT 0 1
test=> SELECT * from emp;
 id | name 
----+-------
  1 | david
  2 | sandy
(2 rows)

test=> \dt
       List of relations
 Schema | Name | Type  | Owner
--------+------+-------+-------
 public | emp  | table | renee
(1 row)

test=> GRANT USAGE ON SCHEMA public to father;
WARNING:  no privileges were granted for "public"
GRANT
test=> GRANT SELECT on public.emp to father;
GRANT
test=>
复制

6.3 创建成员角色

test=> \c postgres postgres
You are now connected to database "postgres" as user "postgres".
postgres=# CREATE ROLE son1 login nosuperuser nocreatedb nocreaterole inherit encrypted password 'abc123';
CREATE ROLE
postgres=#
复制

这里创建了son1 角色,并开启inherit 属性。PostgreSQL 里的角色赋权是通过角色继承(INHERIT)的方式实现的。

6.4 将father 角色赋给son1

postgres=# GRANT father to son1;
GRANT ROLE
postgres=#
复制

还有另一种方法,就是在创建用户的时候赋予角色权限。

postgres=# CREATE ROLE son2 login nosuperuser nocreatedb nocreaterole inherit encrypted password 'abc123' in role father;
CREATE ROLE
postgres=#
复制

6.5 测试son1 角色

postgres=# \c test son1
You are now connected to database "test" as user "son1".
test=> \dt
       List of relations
 Schema | Name | Type  | Owner
--------+------+-------+-------
 public | emp  | table | renee
(1 row)

test=> SELECT * from emp;
 id | name 
----+-------
  1 | david
  2 | sandy
(2 rows)

test=>
用renee 角色新创建一张表,再次测试
test=> \c test renee
You are now connected to database "test" as user "renee".
test=> CREATE TABLE dept (
test(> deptid integer,
test(> deptname text);
CREATE TABLE
test=> INSERT INTO dept (deptid, deptname) values(1, 'ts');
INSERT 0 1
test=> \c test son1
You are now connected to database "test" as user "son1".
test=> SELECT * from dept ;
ERROR:  permission denied for relation dept
test=>
复制

son1 角色只能查询emp 表的数据,而不能查询dept 表的数据,测试成功。

6.6 查询角色组信息

test=> \c postgres postgres
You are now connected to database "postgres" as user "postgres".
postgres=#
postgres=# \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 bella     | Create DB                                      | {}
 david     |                                                | {}
 father    | No inheritance                                 | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 renee     | Create role, Create DB                         | {}
 sandy     |                                                | {}
 son1      |                                                | {father}
 son2      |                                                | {father}

postgres=#
复制

"Member of " 项表示son1 和son2 角色属于father 角色组。


6.7 对整个schema的对象进行权限管理

PostgreSQL 从9.0开始就提供了比较方便的对整个schema的指定对象赋权给目标用的语法。

GRANT
例子

GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
    [, ...] | ALL [ PRIVILEGES ] }
    ON { [ TABLE ] table_name [, ...]
         | ALL TABLES IN SCHEMA schema_name [, ...] }
    TO role_specification [, ...] [ WITH GRANT OPTION ]

REVOKE [ GRANT OPTION FOR ]
    { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
    [, ...] | ALL [ PRIVILEGES ] }
    ON { [ TABLE ] table_name [, ...]
         | ALL TABLES IN SCHEMA schema_name [, ...] }
    FROM { [ GROUP ] role_name | PUBLIC } [, ...]
    [ CASCADE | RESTRICT ]
复制

将schema digoal下的所有表的select,update权限赋予给test用户。

注意

如果digoal.*中包含了非当前用户的表,并且当前用户非超级用户,并且当前用户没有这些表的select,update的with grant option权限。将报错。

换句话说,如果要确保这个赋权操作万无一失,可以选择使用超级用户来执行。


grant select,update on all tables in schema digoal to test;

将schema digoal下的所有表的select,update权限从test用户回收。


revoke select,update on all tables in schema digoal from test;

在对整个schema下的所有对象的权限管理完后, 别忘记了在对象之上,还需要对schema、database、instance进行相应的赋权。


6.8 如何设置用户创建的对象的默认权限

另一个问题,如何设置用户新建的对象的默认权限?

在PostgreSQL 9.0以后新加的语法:

ALTER DEFAULT PRIVILEGES
例如

ALTER DEFAULT PRIVILEGES
    [ FOR { ROLE | USER } target_role [, ...] ]
    [ IN SCHEMA schema_name [, ...] ]
    abbreviated_grant_or_revoke

where abbreviated_grant_or_revoke is one of:

GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
    [, ...] | ALL [ PRIVILEGES ] }
    ON TABLES
    TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
复制

例子:

将digoal用户未来在public下面创建的表的select,update权限默认赋予给test用户.


postgres=> alter default privileges for role digoal in schema public grant select,update on tables to test;
ALTER DEFAULT PRIVILEGES
复制

将test用户未来在public,digoal下面创建的表的select,update权限默认赋予给digoal用户.

postgres=# alter default privileges for role test in schema public,digoal grant select,update on tables to digoal;
ALTER DEFAULT PRIVILEGES
复制

查看已经赋予的默认权限

postgres=> \ddp+
               Default access privileges
  Owner   | Schema | Type  |     Access privileges     
----------+--------+-------+---------------------------
 digoal   | public | table | test=rw/digoal
 test     | digoal | table | digoal=rw/test
 test     | public | table | digoal=rw/test
或

SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS "Owner",
  n.nspname AS "Schema",
  CASE d.defaclobjtype WHEN 'r' THEN 'table' WHEN 'S' THEN 'sequence' WHEN 'f' THEN 'function' WHEN 'T' THEN 'type' END AS "Type",
  pg_catalog.array_to_string(d.defaclacl, E'\n') AS "Access privileges"
FROM pg_catalog.pg_default_acl d
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.defaclnamespace
ORDER BY 1, 2, 3;

  Owner   | Schema | Type  |     Access privileges     
----------+--------+-------+---------------------------
 digoal   | public | table | test=rw/digoal
 postgres |        | table | postgres=arwdDxt/postgres+
          |        |       | digoal=arwdDxt/postgres
 test     | digoal | table | digoal=rw/test
 test     | public | table | digoal=rw/test
(4 rows)
复制



「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论