
关于技术流系列博客
开物成务,厚积薄发。技术流系列博客-以“短小精悍”的形式普及数据库硬核技术。相信大家的每一次阅读,都会距离数据库内核更近一步。每一份来自你们的关注,都是我们坚持输出的满满能量!
一、 行级安全介绍
RLS 主要的应用场景是可以确保不同的用户访问不同的数据内容。例如,针对公司员工信息,某部门组长只能访问与其部门相关的员工信息数据行,而 HR 可以访问整个公司所有员工的信息;一个地区的用户,只能访问该地区用户的数据,不能访问其他地区的用户数据,从而符合数据安全要求和通用数据保护条例(GPDR, General Data Protection Regulation)。
目前大多数数据库,例如 Oracle,SQL Server,PostgreSQL 等,都实现了行级安全控制。后续以 PostgreSQL 的行级安全为例,讲解行级安全控制的功能。
二、 PostgreSQL 行级安全
行级安全可以限制每个用户的正常查询可以返回哪些行,或通过数据修改命令(INSERT、UPDATE、DELETE)修改哪些行。这个特性,就是上述文章提到的 RLS 在 PostgreSQL 中的应用实现。
默认情况下,表没有任何 RSP,因此用户根据 SQL 权限系统对TABLE 有访问权限,表中的所有行都可以进行查询和更新。
当一个 TABLE 启用了 RSP,则所有对 TABLE 数据行正常的查询或修改操作,都必须被 RSP 允许。如果 TABLE 不存在 RSP,则使用默认拒绝策略,意味着没有行可见或可以修改。
RSP 可以指定操作命令、限制角色或两者同时指定;可以指定RSP应用于所有操作命令(ALL),或 SELECT、INSERT、UPDATE 、 DELETE 其中之一;可以将多个角色分配给一个 POLICY,并且正常角色成员资格和继承规则生效。
RLS 的实现逻辑主要是通过控制以下内容:
(1)用户、角色及其成员
(2)操作对象
(3)满足条件的数据
(4)具体命令操作
RLS 的控制主要涉及以下的语法:
(1)行安全策略操作
(2)表 RLS 开关操作
具体操作步骤代码解析如下:
(1)创建 POLICY
CREATE POLICY name ON table_name
[ AS { PERMISSIVE | RESTRICTIVE } ]
[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
[ USING ( using_expression ) ]
[ WITH CHECK ( check_expression ) ]- name
- table_name
- AS 生效策略
- Command
- role_name
- using_expression
- check_expression
(2)修改 POLICY
ALTER POLICY name ON table_name RENAME TO
new_name
ALTER POLICY name ON table_name
[
TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...]
]
[
USING ( using_expression ) ]
[ WITH CHECK
( check_expression ) ](3)删除 POLICY
DROP POLICY [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ](4)修改 TABLE
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
DISABLE ROW LEVEL SECURITY -- 启用RLS
ENABLE ROW LEVEL SECURITY -- 禁用RLS。RSPs可以继续存在。
FORCE ROW LEVEL SECURITY -- RLS应用于TABLE的OWNER
NO FORCE ROW LEVEL SECURITY -- RLS不应用于TABLE的OWNER如果一个表上有多个行安全策略,它们的生效顺序必须满足以下 2 条规则:
(1)当不同命令类型的多个策略应用于同一命令时(例如,SELECT 和 UPDATE 策略应用于一个 UPDATE 命令),那么用户必须同时拥有这两种类型的权限(例如,从 TABLE 中 SELECT 行以及允许 UPDATE 它们的权限)。因此,使用 AND 运算符将两种策略的表达式组合在一起。
(2)当同一命令类型的多个策略应用于同一命令时,必须至少有一个 PERMISSIVE 策略授予对 TABLE 的访问权限,并且所有 RESTRICTIVE 策略都必须通过。因此,所有 PERMISSIVE 策略表达式使用 OR 组合,所有 RESTRICTIVE 策略表达式使用 AND 组合,结果使用 AND 组合;如果没有 PERMISSIVE 策略,则拒绝访问。
定义 POLICY 时,Command 类型和 USING、WITH CHECK 的适用关系如下表所示。

Command 操作类型与 Policy 类型的表达式生效关系图,如下表所示。
[a]:如果需要对现有行或新行进行读取访问(例如,引用关系中列的 WHERE 或 RETURNING 子句),则还需要 SELECT/ALL 策略。
RLS 的使用注意事项:
(1)TABLE 的 owner 才能创建、修改、删除、以及 ENABLE 和 DISABLE POLICY。
(2)TABLE 的 owner 访问数据行通常不受 POLICY 约束,但 owner 可以选择使用 ALTER TABLE ... FORCE ROW LEVEL SECURITY 来接受 RSP 约束。
(3)表上无 RSP,但是启用了表的 RLS,默认拒绝策略(所有行不可读和改)。
(4)TRUNCATE 和 REFERENCES 不受 POLICY 约束。
(5)POLICY 在用户 Queries 指定的条件或函数之前生效(除了 Leakproof 函数,Leakproof 会被优化器选择在 POLICY 之前生效)。
(6)superuser 和具有 BYPASSLRS 属性的角色在访问表时总是绕过 RLS 系统。
(7)一个表可以创建多个 POLICY,Policies 之间不重名。不同表之间的 Policies 命名没有关系,可以重复。
(8)POLICY 的表达式仅考虑要访问或更新行的当前值。
三、 PostgreSQL 行级安全实例





