行级访问控制

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

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

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

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

  1. --创建用户alice, bob, peter
  2. postgres=# CREATE ROLE alice PASSWORD 'xxxxxxxxx';
  3. postgres=# CREATE ROLE bob PASSWORD 'xxxxxxxxx';
  4. postgres=# CREATE ROLE peter PASSWORD 'xxxxxxxxx';
  5. --创建表all_data,包含不同用户数据信息
  6. postgres=# CREATE TABLE all_data(id int, role varchar(100), data varchar(100));
  7. --向数据表插入数据
  8. postgres=# INSERT INTO all_data VALUES(1, 'alice', 'alice data');
  9. postgres=# INSERT INTO all_data VALUES(2, 'bob', 'bob data');
  10. postgres=# INSERT INTO all_data VALUES(3, 'peter', 'peter data');
  11. --将表all_data的读取权限赋予alicebobpeter用户
  12. postgres=# GRANT SELECT ON all_data TO alice, bob, peter;
  13. --打开行访问控制策略开关
  14. postgres=# ALTER TABLE all_data ENABLE ROW LEVEL SECURITY;
  15. --创建行访问控制策略,当前用户只能查看用户自身的数据
  16. postgres=# CREATE ROW LEVEL SECURITY POLICY all_data_rls ON all_data USING(role = CURRENT_USER);
  17. --查看表详细信息
  18. postgres=# \d+ all_data
  19. Table "public.all_data"
  20. Column | Type | Modifiers | Storage | Stats target | Description
  21. --------+------------------------+-----------+----------+--------------+-------------
  22. id | integer | | plain | |
  23. role | character varying(100) | | extended | |
  24. data | character varying(100) | | extended | |
  25. Row Level Security Policies:
  26. POLICY "all_data_rls"
  27. USING (((role)::name = "current_user"()))
  28. Has OIDs: no
  29. Location Nodes: ALL DATANODES
  30. Options: orientation=row, compression=no, enable_rowsecurity=true
  31. --切换至用户alice,执行SQL"SELECT * FROM public.all_data"
  32. postgres=# SELECT * FROM public.all_data;
  33. id | role | data
  34. ----+-------+------------
  35. 1 | alice | alice data
  36. (1 row)
  37. postgres=# EXPLAIN(COSTS OFF) SELECT * FROM public.all_data;
  38. QUERY PLAN
  39. ----------------------------------------------------------------
  40. Streaming (type: GATHER)
  41. Node/s: All datanodes
  42. -> Seq Scan on all_data
  43. Filter: ((role)::name = 'alice'::name)
  44. Notice: This query is influenced by row level security feature
  45. (5 rows)
  46. --切换至用户peter,执行SQL"SELECT * FROM public.all_data"
  47. postgres=# SELECT * FROM public.all_data;
  48. id | role | data
  49. ----+-------+------------
  50. 3 | peter | peter data
  51. (1 row)
  52. postgres=# EXPLAIN(COSTS OFF) SELECT * FROM public.all_data;
  53. QUERY PLAN
  54. ----------------------------------------------------------------
  55. Streaming (type: GATHER)
  56. Node/s: All datanodes
  57. -> Seq Scan on all_data
  58. Filter: ((role)::name = 'peter'::name)
  59. Notice: This query is influenced by row level security feature
  60. (5 rows)