Postgresql 简单的行级安全性 (RLS)

问题描述

我正在努力解决一个基本的行级安全问题。

我首先尝试创建一个“租户”表,其中每一行只能由租户自己看到,然后再将类似的规则应用于引用租户主键的其他表。

我在我的策略中使用会话变量,我还想从客户端强制使用租户 UUID(不是由服务器本身生成的)。

所以一开始我创建了我的表:

CREATE TABLE tenants (
    tenant_id UUID,name text UNIQUE,PRIMARY KEY("tenant_id")
)

然后我启用 RLS 和强制使用给定会话变量的策略:

ALTER TABLE tenants ENABLE ROW LEVEL Security;
CREATE POLICY tenants_isolation_policy ON tenants
        USING (tenant_id = current_setting('my.tenant')::UUID)
        WITH CHECK (tenant_id = current_setting('my.tenant')::UUID)

然后我在 tenants 表中插入 3 个条目:

INSERT INTO "tenants" ("tenant_id","name") VALUES ('9c8e4f83-c036-4fcc-a775-228887d20851','Tenant 1');
INSERT INTO "tenants" ("tenant_id","name") VALUES ('1953be83-683e-4960-a689-db8d53ba8cd2','Tenant 2');
INSERT INTO "tenants" ("tenant_id","name") VALUES ('064767f7-9541-4492-9a7d-0466ac94e2ec','Tenant 3')

然后我冒充租户 1:

SET my.tenant = '9c8e4f83-c036-4fcc-a775-228887d20851'

现在我希望如果我选择所有租户,结果应该只有一行。

然而事实并非如此:

SELECT * FROM tenants

我明白了:

tenant_id 姓名
9c8e4f83-c036-4fcc-a775-228887d20851 租户 1
1953be83-683e-4960-a689-db8d53ba8cd2 租户 2
064767f7-9541-4492-9a7d-0466ac94e2ec 租户 3

在这里错过了什么?政策怎么可能没有被调用

实际上我什至不明白在我还没有设置任何会话变量的情况下我在租户中的插入工作。感觉只是没有考虑 RLS 政策。

解决方法

行级安全有几个例外:

  • 默认情况下,表所有者除外

  • 任何超级用户除外

  • 具有 BYPASSRLS 的任何用户都被排除在外

  • 如果参数 row_security 被关闭,行级安全被禁用

从您的示例来看,您似乎属于第一类。要也为表所有者启用行级安全性,请运行

ALTER TABLE tenants FORCE ROW LEVEL SECURITY;