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

Halo数据库用户角色权限管理

Halo Tech 2025-03-12
232

1、用户和角色

1.1 用户角色概述

    在 Halo 数据库中,角色被广泛用于管理数据库访问权限,以确保数据的安全性和访问控制。角色可以分为以下几类,每种角色具有不同的权限和用途:

1)超级用户(如 halo):超级用户可以绕过除登录权限(login)之外的所有安全检查。超级用户的权限是全局的无法通过 REVOKE命令撤销。即使尝试撤销超级用户的某些权限,Halo也会忽略这些操作。通常用于数据库的系统维护和高级管理任务等。

2)普通用户:根据需要创建,拥有有限的权限。用于日常的数据库操作,如数据查询、插入、更新等。

3)用户(User):拥有登录数据库的权限。

4)角色(Role):可以拥有数据库对象(如表、索引)的权限,并可将这些权限授予其他角色。

5)组(Group):一种特殊的角色,不拥有REPLICATION或 CONNECTION LIMIT 属性。

    角色是在数据库集簇层面上定义的,因此它们在集簇内的所有数据库中都是可用的。即在同一个服务器的不同数据库中,角色是相同的。

核心区别:

对象类型默认属性典型用途
角色(Role)NOLOGIN权限组、逻辑分组
用户(User)LOGIN实际登录的数据库账户

等效关系  

    CREATE USER dev_user;  
    -- 等价于
    CREATE ROLE dev_user LOGIN;

    1.2 创建用户与角色

        在 Halo数据库中,创建用户和角色是权限管理的基础操作。通过 CREATE USER和 CREATE ROLE命令,可以灵活地定义不同类型的用户和角色,并为它们分配相应的角色属性。

      CREATE {USER|ROLE} user_name 
      [ WITH
      [ SUPERUSER | NOSUPERUSER ]
      [ CREATEDB | NOCREATEDB ]
      [ CREATEROLE | NOCREATEROLE ]
      [ INHERIT | NOINHERIT ]
      [ LOGIN | NOLOGIN ]
      [ REPLICATION | NOREPLICATION ]
      [ BYPASSRLS | NOBYPASSRLS ]
      [ CONNECTION LIMIT connlimit ]
      [ VALID UNTIL 'timestamp' ]
      [ IN ROLE role_name [, ...] ]
      [ ROLE role_name [, ...] ]
      [ ADMIN role_name ]
      [ PASSWORD 'password' ]
      ];

      角色属性参数:

      选项意义默认值
      SUPERUSER / NOSUPERUSER角色是否为超级用户,拥有所有权限NOSUPERUSER
      CREATEDB/NOCREATEDB角色是否可以创建数据库NOCREATEDB,SUPERUSER 角色不受此属性影响
      CREATEROLE/NOCREATEROLE角色是否可以创建其他角色NOCREATEDB,SUPERUSER 角色不受此属性影响
      INHERIT/NOINHERIT角色是否继承其父角色的权限INHERIT
      LOGIN/NOLOGIN角色是否可以登录数据库CREATE ROLE默认为 NOLOGIN CREATE USER 默认为 LOGIN,SUPERUSER角色依旧受此属性影响
      REPLICATION/NOREPLICATION角色是否可以用于复制操作NOREPLICATION,SUPERUSER角色不受此属性影响
      BYPASSRLS/NOBYPASSRLS角色是否可以绕过行级安全性(RLS)策略NOBYPASSRLS,SUPERUSER角色不受此属性影响
      CONNECTION LIMIT connlimit角色的最大并发连接数-1(无限制),SUPERUSER 角色不受此属性影响
      [ENCRYPTED] PASSWORD password/ PASSWORD NULL设置角色的密码,空密码导致认证失败未指定则无密码
      VALID UNTIL  'timestamp'设置密码的有效期,过期后密码失效永久有效
      IN ROLE role_name [, ...]将角色添加到指定角色列表中-
      IN GROUP role_name [, ...]与IN ROLE相同,是已过时的语法-
      ROLE role_name [, ...]将指定角色作为新角色的成员-
      ADMIN role_name [, ...]将指定角色作为新角色的管理员成员,并赋予管理权限-

      需要注意:

      1)使用ALTER ROLE修改角色属性,DROP ROLE用于删除角色。角色ROLE默认为NOLOGIN(不可登录数据库),所有CREATE ROLE属性均可被ALTER修改。

      2)属性LOGIN、SUPERUSER、BYPASSRLS、REPLICATION和CREATEROLE被视为特殊权限,它们不会像其它数据库对象的普通权限那样被继承。

      3)使用GRANT和REVOKE增加或移除组角色成员。

      4)VALID UNTIL定义口令过期时间,而不是为一个角色本身定义了一个过期时间。非口令认证时无效。

      5)INHERIT属性控制权限继承,**不适用于特殊角色属性**。

      6)CREATE ROLE无继承概念,可创建权限不同的角色。 

      7)拥有SUPERUSER属性的角色或用户,依然受 LOGIN/ NOLOGIN属性控制是否可登录数据库,

      8)用户角色为数据库中对象拥有者时,删除此用户将会报错,需要更改依赖对象的所有权,或者删除此角色拥有的数据库对象

        -- 先级联删除角色拥有的对象(慎用),再删除角色
        DROP OWNED BY rolename CASCADE;
        DROP ROLE rolename;

        1.3 修改用户角色属性

            创建用户或角色后,可能需要根据实际需求调整其属性,例如更改密码、调整权限、修改角色名称或设置会话参数等。Halo中提供了 ALTER ROLE 和 ALTER USER 语句来修改角色属性。这两个命令在功能上是相似的。

          ALTER {ROLE | USER} role_name [WITH] option;
          -- option 为角色属性,详细参考1.2 中角色属性参数

          还可以使用下列语句更改角色名或角色会话参数值:

          1)使用ALTER ROLE role_name RENAME TO new_role语句重命名角色。

          2)使用ALTER ROLE role_name SET param=value语句更改配置变量的角色会话默认值。

          例如:

          查询系统视图pg_roles可查询角色拥有的属性。

            select * from pg_roles where rolname = 'role_name';

            1.4 角色组权限继承机制

                角色组权限继承是Halo中一种高效且灵活的权限管理机制,通过它可以实现权限的批量分配和集中管理。这种机制允许用户或角色继承所属角色组的权限,从而简化权限的分配和维护过程,同时提高权限管理的可扩展性和可维护性。角色组权限继承是通过创建特定权限的组角色,并将用户或角色分配给这些组角色,实现权限自动传递。组角色无登录权限,但可拥有数据库对象权限。

                如下例,创建了一个名为read_only的角色组,该角色组仅具有对 test 模式下所有表的 USAGE和 SELECT权限。然后,创建了一个名为 dev_user的用户,并将该用户添加到 read_only角色组中,dev_user用户继承了read_only权限,拥有test模式下所有表的 USAGE 和 SELECT权限。

              -- 创建角色组
              CREATE ROLE read_only;
              grant usage on schema test TO read_only;
              GRANT SELECT ON ALL TABLES IN SCHEMA test TO read_only;


              -- 将用户加入角色组
              CREATE USER dev_user;
              GRANT read_only TO dev_user;


              -- 检查角色继承关系
              SELECT
              rolname AS "子角色",
              array_agg(roleid::regrole) AS "继承的父角色"
              FROM pg_auth_members
              JOIN pg_roles ON member = pg_roles.oid
              GROUP BY rolname;


              -- 验证权限继承
              SET ROLE dev_user;
              SELECT * FROM test.products; -- 成功执行
              INSERT INTO test.products(item_id, item_name, price)
              VALUES (1001, 'Special Widget', 49.99); -- 执行失败,无此表insert权限


              -- 将用户移除角色组
              SET ROLE halo;
              REVOKE read_only FROM dev_user;
              SET ROLE dev_user;
              SELECT * FROM test.products; -- 移除角色组无权限,执行失败。

              1.5 权限传递控制(WITH ADMIN OPTION)

                  在 Halo中,权限管理不仅包括授予或撤销角色的权限,还涉及权限的传递控制。通过使用 WITH ADMIN OPTION,可以允许被授权者将角色权限转授给其他用户或角色。这种机制为权限管理提供了更大的灵活性,但是需要谨慎使用,以避免权限扩散带来的安全风险。

                CREATE USER admin_user;
                GRANT read_only TO admin_user WITH ADMIN OPTION;
                -- admin_user 可将 read_only 授予其他用户

                2、数据库级别权限管理

                    数据库级别的权限管理构成了Halo权限体系的核心,主要负责控制用户对数据库的全局访问权限,涵盖连接数据库、创建数据库对象、使用临时表等关键操作。通过恰当配置这些权限,可以有效地限定用户在特定数据库内的活动范围,从而保障数据库的安全性和稳定性。

                2.1 数据库级别权限类别

                权限名称作用描述典型场景
                CONNECT允许用户连接到数据库(基础前置权限普通用户访问生产环境数据库
                CREATE允许用户在指定的数据库中创建新的schema开发者在测试库创建临时 Schema
                TEMPORARY允许创建临时表(会话级存储,常用于复杂查询中间结果)数据分析时存储中间计算结果

                :默认创建的普通用户仅具有CONNECT、TEMPORARY权限,但不具有CREATE权限,即不可在数据库中创建新的数据库对象

                2.2 授权与撤销权限

                   授权和撤销权限是数据库权限管理的核心操作。通过 GRANT和 REVOKE语句,可以精确地控制角色(用户或组)在数据库中的访问权限。下列语句可以授予与撤销角色在数据库上的权限。

                  GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
                  ON DATABASE database_name [, ...]
                  TO role_specification [, ...] [ WITH GRANT OPTION ]


                  REVOKE [ GRANT OPTION FOR ]
                  { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
                  ON DATABASE database_name [, ...]
                  FROM role_specification [, ...]
                  [ CASCADE | RESTRICT ]


                  -- 其中role_specification可以是,[ GROUP ] role_name | PUBLIC | CURRENT_USER | SESSION_USER

                      如果指定了WITH GRANT OPTION,特权的接收者可以接着把它授予给其他人。如果没有授权选项,接收者就不能这样做。授权选项不能被授予给PUBLIC

                      一般情况下,普通用户拥有对数据库的CONNECT与TEMPORARY权限(template0与template1数据库除外)

                     SUPERUSER用户拥有数据库级别所有权限。

                     使用has_database_privilege(RoleName, DbName,PrivilegeType)函数查询用户数据库级别权限,下列语句可查询指定角色的数据库级权限。

                    SELECT 
                    d.datname AS "DbName",
                    r.rolname AS "RoleName",
                    CASE
                    WHEN has_database_privilege(r.rolname, d.datname, 'CONNECT') THEN 'YES'
                    ELSE 'NO'
                    END AS "CONNECT",
                    CASE
                    WHEN has_database_privilege(r.rolname, d.datname, 'CREATE') THEN 'YES'
                    ELSE 'NO'
                    END AS "CREATE",
                    CASE
                    WHEN has_database_privilege(r.rolname, d.datname, 'TEMPORARY') THEN 'YES'
                    ELSE 'NO'
                    END AS "TEMPORARY"
                    FROM
                    pg_roles r, pg_database d
                    WHERE r.rolname = 'username'
                    ORDER BY d.datname;

                    2.3 权限验证操作

                    示例1:测试使用Halo临时表应具有的权限:

                      -- 创建测试用户
                      create user test1;
                      -- 移除默认权限干扰
                      revoke all ON database test FROM public;
                      -- 仅赋予数据库连接权限
                      grant connect on database test TO test1;
                      -- 赋予schema所有权限(排除权限干扰)
                      grant all on schema public TO test1;
                      -- 查看用户权限
                      SELECT
                      d.datname AS "DbName",
                      r.rolname AS "RoleName",
                      CASE
                      WHEN has_database_privilege(r.rolname, d.datname, 'CONNECT') THEN 'YES'
                      ELSE 'NO'
                      END AS "CONNECT",
                      CASE
                      WHEN has_database_privilege(r.rolname, d.datname, 'CREATE') THEN 'YES'
                      ELSE 'NO'
                      END AS "CREATE",
                      CASE
                      WHEN has_database_privilege(r.rolname, d.datname, 'TEMPORARY') THEN 'YES'
                      ELSE 'NO'
                      END AS "TEMPORARY"
                      FROM
                      pg_roles r, pg_database d
                      WHERE r.rolname = 'test1'
                      ORDER BY d.datname;
                      -- 创建全局临时表(验证)
                      \c test test1
                      CREATE TEMPORARY TABLE temp_sales_data (
                      id SERIAL PRIMARY KEY,
                      product_name VARCHAR(100),
                      quantity INT,
                      price NUMERIC(10, 2)
                      ); -- 创建临时表将被拒绝,需要 TEMPORARY 权限
                      \c - halo
                      grant temporary on database test to test1 ; -- 赋予 TEMPORARY 权限
                      \c - test1
                      CREATE TEMPORARY TABLE temp_sales_data (
                      id SERIAL PRIMARY KEY,
                      product_name VARCHAR(100),
                      quantity INT,
                      price NUMERIC(10, 2)
                      ); -- 成功创建临时表

                      示例2:不可移除超级用户的权限,因为超级用户可以绕过除登录权限(login)之外的所有安全检查。

                        -- 创建超级用户
                        create user test2 superuser;
                        -- 查看超级用户数据库级权限
                        SELECT
                        d.datname AS "DbName",
                        r.rolname AS "RoleName",
                        CASE
                        WHEN has_database_privilege(r.rolname, d.datname, 'CONNECT') THEN 'YES'
                        ELSE 'NO'
                        END AS "CONNECT",
                        CASE
                        WHEN has_database_privilege(r.rolname, d.datname, 'CREATE') THEN 'YES'
                        ELSE 'NO'
                        END AS "CREATE",
                        CASE
                        WHEN has_database_privilege(r.rolname, d.datname, 'TEMPORARY') THEN 'YES'
                        ELSE 'NO'
                        END AS "TEMPORARY"
                        FROM
                        pg_roles r, pg_database d
                        WHERE r.rolname = 'test2' AND d.datname = 'test';
                        -- 尝试移除超级用户对test库所有权限,无效
                        revoke all on database test FROM public;
                        revoke all on database test FROM test2;
                        -- 再次查看超级用户数据库级权限,权限未被移除
                        SELECT
                        d.datname AS "DbName",
                        r.rolname AS "RoleName",
                        CASE
                        WHEN has_database_privilege(r.rolname, d.datname, 'CONNECT') THEN 'YES'
                        ELSE 'NO'
                        END AS "CONNECT",
                        CASE
                        WHEN has_database_privilege(r.rolname, d.datname, 'CREATE') THEN 'YES'
                        ELSE 'NO'
                        END AS "CREATE",
                        CASE
                        WHEN has_database_privilege(r.rolname, d.datname, 'TEMPORARY') THEN 'YES'
                        ELSE 'NO'
                        END AS "TEMPORARY"
                        FROM
                        pg_roles r, pg_database d
                        WHERE r.rolname = 'test2' AND d.datname = 'test';
                        \c test test2

                        3、Schema 级权限管理 

                           Schema 级权限管理构成了Halo数据库权限体系的核心部分,它负责控制用户在特定 Schema 中对对象的访问(需配合对象级权限使用)和创建权限。通过恰当配置 Schema 级权限,可以实现对用户操作范围的细致管理,从而确保数据的安全性和隔离性。通常,Schema 级权限需要与对象级权限相结合,以达成更为全面的权限控制。

                        3.1 核心权限类型  

                        权限名称作用描述典型场景
                        USAGE允许访问 Schema 内的对象(需配合对象级权限使用)查询表、调用函数
                        CREATE允许在 Schema 中创建新对象(表、视图、索引等,依赖USAGE权限发环境动态创建测试表

                            一般情况下普通用户拥有public部分系统schemaUSAGE权限,无CREATE权限。Schema 级权限仅控制用户对 Schema 的访问和创建能力,具体对象(如表、视图、函数)的权限还需要通过对象级权限进行管理。Schema 级权限可以通过 GRANT 和 REVOKE语句进行管理,具体操作如下:

                          GRANT { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
                          ON SCHEMA schema_name [, ...]
                          TO role_specification [, ...] [ WITH GRANT OPTION ]


                          REVOKE [ GRANT OPTION FOR ]
                          { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
                          ON SCHEMA schema_name [, ...]
                          FROM role_specification [, ...]
                          [ CASCADE | RESTRICT ]
                          -- 其中role_specification可以是,[ GROUP ] role_name | PUBLIC | CURRENT_USER | SESSION_USER

                          3.2 权限查询方法  

                          has_schema_privilege(RoleName,SchemaName,PrivilegeType)函数查询用户Schema级别权限,用于检查指定角色(用户或组)是否拥有对某个 Schema 的特定权限。下列语句可查询指定角色的schema级权限。

                            SELECT 
                            n.nspname AS schema_name,
                            r.rolname AS rolname,
                            CASE
                            WHEN has_schema_privilege(r.rolname, n.nspname, 'USAGE') THEN 'YES'
                            ELSE 'NO'
                            END AS "USAGE",
                            CASE
                            WHEN has_schema_privilege(r.rolname, n.nspname, 'CREATE') THEN 'YES'
                            ELSE 'NO'
                            END AS "CREATE"
                            FROM
                            pg_roles r
                            JOIN pg_namespace n ON true
                            WHERE r.rolname = 'username'
                            ORDER BY n.nspname;

                            3.3 权限验证操作

                            示例1:数据库级CREATE与schema级别的CREATE权限对比

                              -- 创建测试用户
                              create user test1;
                              create user test2;
                              -- 移除测试库权限干扰
                              revoke create on database test FROM public;
                              revoke create on schema public FROM public;
                              -- 赋予 test1 数据库级别 create权限
                              grant create on database test TO test1;
                              -- 赋予 tes2 schema 级别 create权限
                              grant create on schema public TO test2;
                              -- 查看两个用户数据库级权限
                              SELECT
                              d.datname AS "DbName",
                              r.rolname AS "RoleName",
                              CASE
                              WHEN has_database_privilege(r.rolname, d.datname, 'CONNECT') THEN 'YES'
                              ELSE 'NO'
                              END AS "CONNECT",
                              CASE
                              WHEN has_database_privilege(r.rolname, d.datname, 'CREATE') THEN 'YES'
                              ELSE 'NO'
                              END AS "CREATE",
                              CASE
                              WHEN has_database_privilege(r.rolname, d.datname, 'TEMPORARY') THEN 'YES'
                              ELSE 'NO'
                              END AS "TEMPORARY"
                              FROM
                              pg_roles r, pg_database d
                              WHERE (r.rolname = 'test1' OR r.rolname = 'test2') AND d.datname = 'test';
                              -- 验证数据库级 CREATE 权限
                              \c test test1
                              create schema test1; -- 创建成功,test1拥有数据库级别 create
                              \c test test2
                              create schema test2; -- 执行失败,无权
                              -- 查看两个用户schema级权限
                              SELECT
                              n.nspname AS schema_name,
                              r.rolname AS rolname,
                              CASE
                              WHEN has_schema_privilege(r.rolname, n.nspname, 'USAGE') THEN 'YES'
                              ELSE 'NO'
                              END AS "USAGE",
                              CASE
                              WHEN has_schema_privilege(r.rolname, n.nspname, 'CREATE') THEN 'YES'
                              ELSE 'NO'
                              END AS "CREATE"
                              FROM
                              pg_roles r
                              JOIN pg_namespace n ON true
                              WHERE (r.rolname = 'test1' OR r.rolname = 'test2') AND n.nspname = 'public';
                              -- 验证 schema 级 CREATE 权限
                              \c test test1
                              CREATE TABLE public.test_table (
                              id SERIAL PRIMARY KEY,
                              name VARCHAR(50)
                              ); -- test1无 public 的 CREATE 权限,执行失败
                              \c test test2
                              CREATE TABLE public.test_table (
                              id SERIAL PRIMARY KEY,
                              name VARCHAR(50)
                              ); -- 执行成功

                              示例2:schema级USAGE权限需配合对象级权限使用

                                -- 创建测试用户
                                create user test1;
                                create user test2;
                                -- 移除test1 USAGE权限
                                revoke USAGE on schema public FROM test1;
                                -- 赋予 tes2 schema 级别 create权限
                                grant create on schema public TO test2;
                                -- 创建测试表
                                \c test test2
                                CREATE TABLE public.test_table (
                                id SERIAL PRIMARY KEY,
                                name VARCHAR(50)
                                ); -- 执行成功
                                \dt public.test_table
                                -- 查看两个用户schema级权限
                                SELECT
                                n.nspname AS schema_name,
                                r.rolname AS rolname,
                                CASE
                                WHEN has_schema_privilege(r.rolname, n.nspname, 'USAGE') THEN 'YES'
                                ELSE 'NO'
                                END AS "USAGE",
                                CASE
                                WHEN has_schema_privilege(r.rolname, n.nspname, 'CREATE') THEN 'YES'
                                ELSE 'NO'
                                END AS "CREATE"
                                FROM
                                pg_roles r
                                JOIN pg_namespace n ON true
                                WHERE (r.rolname = 'test1' OR r.rolname = 'test2') AND n.nspname = 'public';
                                -- 查询public.test_table
                                select * from public.test_table;
                                -- 赋予test1 USAGE 权限
                                \c test halo
                                grant USAGE on schema public TO public;
                                -- test1 虽有 USAGE 权限 ,但无此表 select 权限(需配合对象级权限)
                                \c test test1
                                select has_table_privilege('test1','public.test_table','select');
                                select * from public.test_table;
                                -- 赋予test1 select 表权限
                                \c test halo
                                grant select ON table public.test_table TO test1;
                                \c test test1
                                select * from public.test_table; -- 执行成功

                                4、元对象级权限管理

                                    元对象级权限管理是 Halo中最细粒度的权限控制方式,用于控制用户对具体对象(如表、视图、函数、序列等)的操作权限。这种权限管理方式允许数据库管理员根据用户的角色和需求,精确地授予或撤销对特定对象的访问权限。对于使用schema中元对象,首先得拥有对schema的USAGE权限,必要情况下还需拥有schema的CREATE权限

                                4.1 表与视图权限  

                                    表和视图的权限管理是 Halo中重要的安全机制,用于控制用户对数据的访问和操作能力。以下是表和视图的常见权限类型及其作用描述和依赖关系:

                                权限名称作用描述依赖关系
                                SELECT读取数据(视图必备权限)
                                INSERT插入新数据
                                UPDATE修改数据
                                DELETE删除数据
                                TRUNCATE快速清空表数据
                                REFERENCES创建外键约束被引用表需有此权限
                                TRIGGER创建/删除触发器表所有者权限

                                列语句可以授予与撤销角色对表或视图的权限。

                                  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 ]


                                  -- 可对特定列赋权
                                  GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] )
                                  [, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) }
                                  ON [ TABLE ] table_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 role_specification [, ...]
                                  [ CASCADE | RESTRICT ]


                                  -- 可对特定列进行权限回收
                                  REVOKE [ GRANT OPTION FOR ]
                                  { { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] )
                                  [, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) }
                                  ON [ TABLE ] table_name [, ...]
                                  FROM role_specification [, ...]
                                  [ CASCADE | RESTRICT ]

                                  通过 information_schema.table_privileges视图或者 has_table_privilege(RoleName,TableName,PrivilegeType) 函数可查询用户对表的相关权限。语句如下:

                                    -- 通过视图查询
                                    SELECT grantee, table_schema, table_name, privilege_type
                                    FROM information_schema.table_privileges
                                    WHERE grantee = 'username' AND table_name = 'table_name';


                                    -- 通过快捷键查询
                                    \dp+ TableName


                                    -- 例如:
                                    test=# \dp+ public.test_table
                                    Access privileges
                                    Schema | Name | Type | Access privileges | Column privileges | Policies
                                    --------+------------+-------+---------------------+-------------------+----------
                                    public | test_table | table | test2=arwdDxt/test2+| |
                                    | | | test1=arwdDxt/test2 | |
                                    (1 row)


                                    -- 权限标识符说明:
                                    a=INSERT, r=SELECT, w=UPDATE, d=DELETE, D=TRUNCATE, x=REFERENCES, t=TRIGGER *=WITH GRANT OPTION(表示可转授权限)

                                    以下是一个完整的测试示例,用于验证 Halo 中的列级安全功能。将创建一个表 employees,为用户 test1 赋予对部分列(name, department)的权限,并验证列级安全。

                                      -- 创建测试表
                                      CREATE TABLE public.employees (
                                      id SERIAL PRIMARY KEY,
                                      name TEXT NOT NULL,
                                      salary NUMERIC(10, 2),
                                      department TEXT
                                      );
                                      INSERT INTO public.employees (name, salary, department)
                                      VALUES
                                      ('Alice', 5000.00, 'HR'),
                                      ('Bob', 6000.00, 'Engineering'),
                                      ('Charlie', 7000.00, 'Finance');
                                      -- 创建测试用户并赋权
                                      create user test1;
                                      grant all (name, department) on table public.employees to test1;
                                      -- 查看表权限
                                      \dp+ public.employees
                                      -- 列级安全测试
                                      \c test test1
                                      SELECT name, department from public.employees; -- 查询授权列,成功
                                      SELECT name, salary, department from public.employees; -- 查询包含未授权列,执行失败

                                       4.2 函数与序列权限

                                      对象类型权限名称作用描述依赖关系
                                      函数、存过(FUNCTION、PROCEDURE、ROUTINE)EXECUTE执行函数/存储过程
                                      序列USAGE访问序列值
                                      序列SELECT使用 nextval()/currval()
                                      序列UPDATE修改序列值 (setval())需 USAGE

                                      下列语句可以授予与撤销函数与序列的权限。

                                        GRANT { EXECUTE | ALL [ PRIVILEGES ] }
                                        ON { { FUNCTION | PROCEDURE | ROUTINE } routine_name [ ( [ [ argmode ]
                                        [ arg_name ] arg_type [, ...] ] ) ] [, ...]
                                        | ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA schema_name
                                        [, ...] }
                                        TO role_specification [, ...] [ WITH GRANT OPTION ]


                                        GRANT { { USAGE | SELECT | UPDATE }
                                        [, ...] | ALL [ PRIVILEGES ] }
                                        ON { SEQUENCE sequence_name [, ...]
                                        | ALL SEQUENCES IN SCHEMA schema_name [, ...] }
                                        TO role_specification [, ...] [ WITH GRANT OPTION ]




                                        REVOKE [ GRANT OPTION FOR ]
                                        { EXECUTE | ALL [ PRIVILEGES ] }
                                        ON { { FUNCTION | PROCEDURE | ROUTINE } function_name [ ( [ [ argmode ]
                                        [ arg_name ] arg_type [, ...] ] ) ] [, ...]
                                        | ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA schema_name
                                        [, ...] }
                                        FROM role_specification [, ...]
                                        [ CASCADE | RESTRICT ]


                                        REVOKE [ GRANT OPTION FOR ]
                                        { { USAGE | SELECT | UPDATE }
                                        [, ...] | ALL [ PRIVILEGES ] }
                                        ON { SEQUENCE sequence_name [, ...]
                                        | ALL SEQUENCES IN SCHEMA schema_name [, ...] }
                                        FROM role_specification [, ...]
                                        [ CASCADE | RESTRICT ]


                                        -- 若需要将整个shcema下的函数、存过和序列赋予某用户时,可使用下列语句
                                        grant all on all ROUTINES IN SCHEMA schema_name to rolename;
                                        grant all on all SEQUENCES IN SCHEMA schema_name to rolename;

                                        通过查询函数 has_function_privilege(RoleName,FunName,PrivilegeType)、has_sequence_privilege(RoleName,SequenceName,PrivilegeType)

                                        如下例:

                                        4.3 外部对象权限

                                        对象类型权限名称作用描述
                                        外部数据包装器 (FOREIGN DATA WRAPPER)USAGE使用外部数据包装器
                                        外部服务器(FOREIGN SERVER)USAGE使用外部服务器配置
                                        域 (DOMAIN)USAGE使用自定义域类型
                                        类型 (TYPE)USAGE使用自定义数据类型

                                        下列语句可以授予与撤销角色对外部对象的权限。

                                          GRANT { USAGE | ALL [ PRIVILEGES ] }
                                          ON { DOMAIN domain_name [, ...] | FOREIGN DATA WRAPPER fdw_name [, ...]
                                          | FOREIGN SERVER server_name [, ...] | TYPE type_name [, ...] }
                                          TO role_specification [, ...] [ WITH GRANT OPTION ]


                                          REVOKE [ GRANT OPTION FOR ]
                                          { USAGE | ALL [ PRIVILEGES ] }
                                          ON { DOMAIN domain_name [, ...] | FOREIGN DATA WRAPPER fdw_name [, ...]
                                          | FOREIGN SERVER server_name [, ...] | TYPE type_name [, ...] }
                                          FROM role_specification [, ...]
                                          [ CASCADE | RESTRICT ]

                                          使用函数has_foreign_data_wrapper_privilege(RoleName,FdwName,PrivilegeType)has_server_privilege(RoleName,ServerName,PrivilegeType)has_type_privilege(RoleName,TypeName,PrivilegeType)可查询相关对象权限,此处不再示例展出。

                                           4.4 大对象与表空间权限

                                          对象类型权限名称作用描述
                                          大对象(LARGE OBJECT)SELECT读取大对象内容
                                          大对象(LARGE OBJECT)UPDATE修改大对象内容
                                          表空间(TABLESPACE)CREATE在表空间创建对象

                                          下列语句可以授予与撤销角色对大对象与表空间的权限。

                                            GRANT { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
                                            ON LARGE OBJECT loid [, ...]
                                            TO role_specification [, ...] [ WITH GRANT OPTION ]


                                            GRANT { CREATE | ALL [ PRIVILEGES ] }
                                            ON TABLESPACE tablespace_name [, ...]
                                            TO role_specification [, ...] [ WITH GRANT OPTION ]


                                            REVOKE [ GRANT OPTION FOR ]
                                            { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
                                            ON LARGE OBJECT loid [, ...]
                                            FROM role_specification [, ...]
                                            [ CASCADE | RESTRICT ]


                                            REVOKE [ GRANT OPTION FOR ]
                                            { CREATE | ALL [ PRIVILEGES ] }
                                            ON TABLESPACE tablespace_name [, ...]
                                            FROM role_specification [, ...]
                                            [ CASCADE | RESTRICT ]

                                            使用函数has_tablespace_privilege(RoleName,TablespaceName,PrivilegeType)可对查询表空间相关权限。

                                            4.5 其他对象权限 

                                            对象类型权限名称作用描述
                                            语言(LANGUAGE)USAGE使用编程语言
                                            触发器(TRIGGER)隐式拥有通过表TRIGGER权限控制

                                            下列语句可以授予与撤销角色对语言的权限。

                                              GRANT { USAGE | ALL [ PRIVILEGES ] }
                                              ON LANGUAGE lang_name [, ...]
                                              TO role_specification [, ...] [ WITH GRANT OPTION ]


                                              REVOKE [ GRANT OPTION FOR ]
                                              { USAGE | ALL [ PRIVILEGES ] }
                                              ON LANGUAGE lang_name [, ...]
                                              FROM role_specification [, ...]
                                              [ CASCADE | RESTRICT ]

                                              4.6 行级安全(Row-Level Security,RLS)

                                                  RLS是一种强大的功能,用于通过基于用户角色、属性或其他条件的细粒度访问控制来限制对表中行的访问。RLS 在多租户应用程序或管理敏感数据时非常有用。默认情况下,表的行级安全是禁用的。启用行级安全后,如果没有定义任何策略,默认策略是“拒绝所有”(default-deny),即没有任何行对用户可见(超级用户可绕过此限制)。要启用行级安全,可以使用以下命令:

                                                -- 启用行级安全
                                                ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;

                                                下例中

                                                  -- 创建数据库 hr
                                                  CREATE DATABASE hr;


                                                  -- 切换到 hr 数据库
                                                  \c hr


                                                  -- 创建 departments 表
                                                  CREATE TABLE departments (
                                                  id SERIAL PRIMARY KEY,
                                                  name VARCHAR(255) NOT NULL UNIQUE,
                                                  manager VARCHAR(255) NOT NULL
                                                  );


                                                  -- 插入初始数据
                                                  INSERT INTO departments (name, manager)
                                                  VALUES
                                                  ('Sales', 'alice'),
                                                  ('Marketing', 'bob'),
                                                  ('IT', 'jack');


                                                  -- 创建组角色 managers
                                                  CREATE ROLE managers;


                                                  -- 授予 managers 角色对 public 模式中所有表的 SELECT 权限
                                                  GRANT SELECT ON ALL TABLES IN SCHEMA public TO managers;


                                                  -- 创建部门经理角色并分配到 managers 组
                                                  CREATE ROLE alice WITH LOGIN IN ROLE managers;
                                                  CREATE ROLE bob WITH LOGIN IN ROLE managers;
                                                  CREATE ROLE jack WITH LOGIN IN ROLE managers;


                                                  -- 在 departments 表上启用行级安全性
                                                  ALTER TABLE departments ENABLE ROW LEVEL SECURITY;


                                                  -- 创建行级安全策略
                                                  CREATE POLICY department_managers
                                                  ON departments
                                                  FOR SELECT
                                                  USING (manager = current_user);


                                                  -- 使用 alice 角色连接到 hr 数据库
                                                  \c hr alice
                                                  -- 查询 departments 表
                                                  SELECT * FROM departments;


                                                  -- 使用 bob 角色连接到 hr 数据库
                                                  \c hr bob
                                                  -- 查询 departments 表
                                                  SELECT * FROM departments;


                                                  -- 使用超级用户连接到 hr 数据库
                                                  \c hr halo
                                                  SELECT * FROM departments;

                                                  4.7 权限生效判断逻辑  

                                                  文章转载自Halo Tech,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                                  评论