更新时间:2024-11-12 GMT+08:00
分享

行级访问控制

行级访问控制特性将数据库访问控制精确到数据表行级别,使数据库达到行级访问控制的能力。不同用户执行相同的SQL查询操作,读取到的结果是不同的。

用户可以在数据表创建行访问控制(Row Level Security)策略,该策略是指针对特定数据库用户、特定SQL操作生效的表达式。当数据库用户对数据表访问时,若SQL满足数据表特定的Row Level Security策略,在查询优化阶段将满足条件的表达式,按照属性(PERMISSIVE | RESTRICTIVE)类型,通过AND或OR方式拼接,应用到执行计划上。

行级访问控制的目的是控制表中行级数据可见性,通过在数据表上预定义Filter,在查询优化阶段将满足条件的表达式应用到执行计划上,影响最终的执行结果。当前受影响的SQL语句包括SELECT、UPDATE和DELETE。

场景一:某表中汇总了不同用户的数据,但是不同用户只能查看自身相关的数据信息,不能查看其他用户的数据信息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
--创建用户alice, bob, peter
gaussdb=# CREATE USER alice PASSWORD '********';
gaussdb=# CREATE USER bob PASSWORD '********';
gaussdb=# CREATE USER peter PASSWORD '********';

--创建表all_data,包含不同用户数据信息
gaussdb=# CREATE TABLE all_data(id int, role varchar(100), data varchar(100));

--向数据表插入数据
gaussdb=# INSERT INTO all_data VALUES(1, 'alice', 'alice data');
gaussdb=# INSERT INTO all_data VALUES(2, 'bob', 'bob data');
gaussdb=# INSERT INTO all_data VALUES(3, 'peter', 'peter data');

--将表all_data的读取权限赋予alice,bob和peter用户
gaussdb=# GRANT SELECT ON all_data TO alice, bob, peter;

--打开行访问控制策略开关
gaussdb=# ALTER TABLE all_data ENABLE ROW LEVEL SECURITY;

--创建行访问控制策略,当前用户只能查看用户自身的数据
gaussdb=# CREATE ROW LEVEL SECURITY POLICY all_data_rls ON all_data USING(role = CURRENT_USER);

--查看表详细信息
gaussdb=# \d+ all_data
                               Table "public.all_data"
 Column |          Type          | Modifiers | Storage  | Stats target | Description
--------+------------------------+-----------+----------+--------------+-------------
 id     | integer                |           | plain    |              |
 role   | character varying(100) |           | extended |              |
 data   | character varying(100) |           | extended |              |
Row Level Security Policies:
    POLICY "all_data_rls" FOR ALL
      TO public
      USING (((role)::name = "current_user"()))
Has OIDs: no
Distribute By: HASH(id)
Location Nodes: ALL DATANODES
Options: orientation=row, compression=no, enable_rowsecurity=true

--切换至用户alice,执行SQL"SELECT * FROM public.all_data"
gaussdb=# SELECT * FROM public.all_data;
 id | role  |    data
----+-------+------------
  1 | alice | alice data
(1 row)

gaussdb=# EXPLAIN(COSTS OFF) SELECT * FROM public.all_data;
                           QUERY PLAN
----------------------------------------------------------------
 Streaming (type: GATHER)
   Node/s: All datanodes
   ->  Seq Scan on all_data
         Filter: ((role)::name = 'alice'::name)
 Notice: This query is influenced by row level security feature
(5 rows)

--切换至用户peter,执行SQL"SELECT * FROM public.all_data"
gaussdb=# SELECT * FROM public.all_data;
 id | role  |    data
----+-------+------------
  3 | peter | peter data
(1 row)

gaussdb=# EXPLAIN(COSTS OFF) SELECT * FROM public.all_data;
                           QUERY PLAN
----------------------------------------------------------------
 Streaming (type: GATHER)
   Node/s: All datanodes
   ->  Seq Scan on all_data
         Filter: ((role)::name = 'peter'::name)
 Notice: This query is influenced by row level security feature
(5 rows)
  • PG_STATISTIC系统表和PG_STATISTIC_EXT系统表存储了统计对象的一些敏感信息,如高频值MCV。若创建行级访问控制后,将这两张系统表的查询权限授予普通用户,则普通用户仍然可以通过访问这两张系统表,获取统计对象里的敏感信息。
  • PG_STATS、PG_EXT_STATS、PG_GTT_STATS为统计信息查询视图,校验用户对列的SELECT权限。若普通用户拥有SELECT权限且表上存在行级访问控制,可能查询到无法查询但刚好出现在统计信息高频值里的部分数据(非整行数据,仅是某列的一个值,统计信息是按列收集计算的)。

相关文档