如果说基于角色和表的权限像是“门口的保安”,那 Row-Level Security 就像是每个房间门口都站着一个专属保安,检查每个用户能不能进这间房。
RLS 能让用户只能操作他被允许的表里的那些行。比如:
- 在网店里,经理只能看到自己的订单。
- 在 CRM 平台,员工只能看到自己团队的客户。
- 在银行系统,客户只能访问自己的账户。
RLS 怎么工作
RLS 的核心就是访问策略。策略决定了哪些表的行对某个角色或用户可见,哪些可以被改(INSERT、UPDATE、DELETE)。
默认情况下,RLS 是关闭的,你得手动开启。
为表开启 RLS
咱们先建个 orders 表,存网店订单:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
user_id INT NOT NULL,
product_name TEXT NOT NULL,
price NUMERIC NOT NULL
);
插入几条测试数据:
INSERT INTO orders (user_id, product_name, price)
VALUES
(1, '智能手机', 500),
(2, '笔记本', 1000),
(1, '耳机', 100),
(3, '键盘', 50);
现在给这个表开启 RLS:
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
我们做了啥?就是激活了 RLS 机制,但还没设任何策略。没策略的话,RLS 实际上对表没啥影响。
创建访问策略
要加访问规则,用这个命令:
CREATE POLICY 策略名
ON 表名
[FOR { SELECT | INSERT | UPDATE | DELETE }]
TO 角色
USING (访问条件)
WITH CHECK (检查条件);
FOR:指定策略应用在哪些操作(SELECT、INSERT、UPDATE、DELETE)。不写就所有操作都用。TO:指定哪些角色用这个策略。不写就是所有角色都用。USING:设置什么条件下行对用户可见。WITH CHECK:给INSERT和UPDATE操作用的检查条件。
例子:只能访问自己的订单
来建个策略,让用户只能看到自己的订单。假设当前用户的 id 跟表里的 user_id 一样:
CREATE POLICY user_can_view_own_orders
ON orders
FOR SELECT
USING (user_id = current_user::INT);
这段代码干了啥?
- 策略名叫
user_can_view_own_orders。 - 只对
SELECT操作生效。 - 只有
user_id跟当前用户 id(current_user)一样的行才可见。
所以你用 user_id = 1 登录,只能看到自己的订单。
测试 RLS 效果
建两个用户:user1 和 user2。
CREATE ROLE user1 LOGIN PASSWORD 'password1';
CREATE ROLE user2 LOGIN PASSWORD 'password2';
给这俩角色授权访问表:
GRANT SELECT ON orders TO user1, user2;
现在切换到 user1,试试查表:
SELECT * FROM orders;
结果:你只能看到 user_id = 1 的行。
INSERT 策略
比如我们想让用户只能添加属于自己的订单(也就是 user_id 必须等于当前用户 id)。
建个 INSERT 策略:
CREATE POLICY user_can_insert_own_orders
ON orders
FOR INSERT
WITH CHECK (user_id = current_user::INT);
现在,如果 user1 想插入 user_id 不是 1 的订单,会报错。
UPDATE 和 DELETE 策略
同理可以建修改和删除的策略。比如:
只能改自己的数据:
CREATE POLICY user_can_update_own_orders
ON orders
FOR UPDATE
USING (user_id = current_user::INT)
WITH CHECK (user_id = current_user::INT);
只能删自己的数据:
CREATE POLICY user_can_delete_own_orders
ON orders
FOR DELETE
USING (user_id = current_user::INT);
多策略同时用
你可以给一个表建多个策略,都会一起生效。如果一个角色有多条规则,PostgreSQL 会都检查一遍(逻辑与)。
RLS 检查和调试
想查表上有哪些策略,用:
\di+ 表名
想临时关掉 RLS(比如管理员用),执行:
ALTER TABLE orders DISABLE ROW LEVEL SECURITY;
超级管理员 SUPERUSER 默认不受 RLS 限制,可以看到所有数据。
RLS 配置常见错误
常见错误有:
- 忘了用
ALTER TABLE ... ENABLE ROW LEVEL SECURITY开启 RLS。 - 没给所有操作(
SELECT、INSERT、UPDATE、DELETE)设策略。 USING和WITH CHECK条件写错。比如没检查user_id,就可能让所有行都能访问。
Row-Level Security 是 PostgreSQL 里最强大的安全工具之一。它能精确到每一行控制访问,还能自动化管理权限,特别适合对数据安全要求高的复杂应用。
GO TO FULL VERSION