PostgreSQL对所有用户强制行级安全(RLS)后超级用户仍可查询全量数据的问题
我完全理解你此刻的困惑——明明已经按步骤做了强制RLS的配置,包括给超级用户postgres设置NOBYPASSRLS、给表启用并强制RLS,甚至建了一个完全禁止操作的策略,但postgres还是能查到所有数据,这确实有点出乎意料。
先复盘一下你已经执行的操作:
ALTER ROLE postgres WITH NOBYPASSRLS; -- 尝试对超级用户强制RLS ALTER TABLE items ENABLE ROW LEVEL SECURITY; ALTER TABLE items FORCE ROW LEVEL SECURITY; -- 强制表所有者遵守RLS CREATE POLICY never_anything_policy ON items FOR ALL -- 禁止所有操作 USING (false); -- 条件永远不成立
问题的核心在于PostgreSQL超级用户的特殊权限豁免机制:
即使你给postgres设置了NOBYPASSRLS,只要这个角色还是超级用户,它就会自动绕过所有RLS限制——这是PostgreSQL内置的规则,超级用户本质上拥有系统的最高权限,不受行级安全策略的约束,哪怕你设置了FORCE ROW LEVEL SECURITY也没用。
那怎么解决这个问题?有两种思路:
1. 更推荐的方案:使用普通管理员角色替代postgres日常操作
不要直接用postgres超级用户做业务操作,创建一个专门的管理员角色,给它必要的管理权限(比如CREATEDB、CREATEROLE),但不赋予超级用户权限:
-- 创建普通管理员角色 CREATE ROLE admin_user WITH LOGIN PASSWORD 'your_password' CREATEDB CREATEROLE; -- 给它items表的必要权限(根据需求调整) GRANT SELECT, INSERT, UPDATE, DELETE ON items TO admin_user;
之后用这个admin_user进行日常管理,它会严格遵守你设置的RLS规则,而postgres只保留用于紧急系统维护的用途。
2. 极端方案:撤销postgres的超级用户权限
如果你一定要让postgres也遵守RLS,可以撤销它的超级用户属性,但强烈不推荐这个做法——万一后续需要系统级操作,你可能会陷入无法恢复的困境,除非你已经提前创建了其他超级用户。执行命令如下:
ALTER ROLE postgres WITH NOSUPERUSER;
执行后,postgres就会像普通角色一样遵守RLS规则,但你要确保自己有其他超级用户账号可以用来恢复权限。
最后再补充一点:你的FORCE ROW LEVEL SECURITY设置是有效的,它会让表的所有者(非超级用户)必须遵守RLS,但超级用户不在这个规则的约束范围内,这是需要明确的区别。
备注:内容来源于stack exchange,提问作者Joost Dübken

