将 PostgreSQL 行级安全 (RLS) 策略与 current_setting() 函数结合使用
Using PostgreSQL row level security (RLS) policies with current_setting() function
我已将 RLS 策略应用到“用户”table,并希望只检索具有 tenant_id=2
的记录:
CREATE TABLE "users" ("name" text UNIQUE NOT NULL, "tenant_id" int NOT NULL DEFAULT current_setting('app.current_tenant')::int);
--Enable Row Security Policies
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE users FORCE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation_policy ON users USING (tenant_id = current_setting('app.current_tenant')::int);
--Set "111" as the current tenant.
SET app.current_tenant TO 1;
INSERT INTO users VALUES ('admin');
INSERT INTO users VALUES ('bob');
--Set "222" as the current tenant.
SET app.current_tenant TO 2;
INSERT INTO users VALUES ('alice');
--Data output
SELECT * FROM users;
但我在结果中得到了所有用户:
name tenant_id
admin 1
bob 1
alice 2
为什么会这样?
这是我坚持使用的 dbFiddle:
https://www.db-fiddle.com/f/iFktvVsDNYKggUNT2oDJBV/0
有四个原因可以绕过行级安全:
用户是table的所有者。
您可以使用
使 table 所有者受到行级安全性的约束
ALTER TABLE users FORCE ROW LEVEL SECURITY;
用户是超级用户。
用户是用 BYPASSRLS
创建的。
数据库参数row_security
设置为off
。
请注意,使用带有占位符参数的行级安全性本质上是不安全的:如果攻击者可以发出 SQL 语句(例如,通过 SQL 注入),他们只需将值更改为他们喜欢什么。
我已将 RLS 策略应用到“用户”table,并希望只检索具有 tenant_id=2
的记录:
CREATE TABLE "users" ("name" text UNIQUE NOT NULL, "tenant_id" int NOT NULL DEFAULT current_setting('app.current_tenant')::int);
--Enable Row Security Policies
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE users FORCE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation_policy ON users USING (tenant_id = current_setting('app.current_tenant')::int);
--Set "111" as the current tenant.
SET app.current_tenant TO 1;
INSERT INTO users VALUES ('admin');
INSERT INTO users VALUES ('bob');
--Set "222" as the current tenant.
SET app.current_tenant TO 2;
INSERT INTO users VALUES ('alice');
--Data output
SELECT * FROM users;
但我在结果中得到了所有用户:
name tenant_id
admin 1
bob 1
alice 2
为什么会这样?
这是我坚持使用的 dbFiddle: https://www.db-fiddle.com/f/iFktvVsDNYKggUNT2oDJBV/0
有四个原因可以绕过行级安全:
用户是table的所有者。
您可以使用
使 table 所有者受到行级安全性的约束ALTER TABLE users FORCE ROW LEVEL SECURITY;
用户是超级用户。
用户是用
BYPASSRLS
创建的。数据库参数
row_security
设置为off
。
请注意,使用带有占位符参数的行级安全性本质上是不安全的:如果攻击者可以发出 SQL 语句(例如,通过 SQL 注入),他们只需将值更改为他们喜欢什么。