PostgreSQL RLS隐式与显式策略的安全性是否等价?
PostgreSQL RLS两组策略安全等价性判定
结论:两组策略安全层面不完全等价,核心差异为UPDATE操作是否允许修改RLS关联的id字段值
1. 两组策略的UPDATE行为差异
PostgreSQL官方文档明确说明:「任何更新后的值未通过WITH CHECK表达式校验的行都会触发错误,整个命令会被中止。如果仅指定了USING子句,则该子句会同时用于USING和WITH CHECK场景。」
你之前的理解完全正确,二者的UPDATE规则差异如下:
- 隐式单条策略的UPDATE规则:
因为全局指定了WITH CHECK (TRUE),对UPDATE操作来说,只要满足USING条件(原行id等于当前rls.id)就可以修改,更新后的行不受任何校验,允许用户将自己名下的行的id修改为任意值。 - 拆分显式策略的UPDATE规则:
仅指定了USING子句,WITH CHECK会复用USING的id = current_setting('rls.id'::TEXT)逻辑,要求更新后的行的id也必须等于当前rls.id,禁止用户修改行的id字段,也禁止将id改为其他用户的值。
2. 实际风险场景示例
假设当前会话设置SET rls.id = '1',且存在一行id=1的测试数据:
- 执行
UPDATE test SET id = 2 WHERE id = 1;- 用隐式单条策略:执行成功,该行的id被改为2,直接归属到id=2的用户名下,当前会话再也查询不到该行
- 用拆分显式策略:执行直接报错,更新被拦截,不存在数据越权转移的风险
3. 测试未发现差异的原因
大概率是测试时没有覆盖修改id字段的场景,只有当更新操作涉及id字段修改时,二者的安全差异才会显现。
内容的提问来源于stack exchange,提问作者Giannis Dim
相关产品推荐
相关产品推荐

