PostgreSQL行级权限配置问题:通用策略为何限制插入操作?
PostgreSQL RLS策略配置错误分析
需求
让public.services_connected表对anon用户禁止SELECT操作,但允许执行INSERT、UPDATE、DELETE操作。
最初的错误配置
create policy "workspace_only" on "public"."services_connected" as restrictive for all to anon using ((workspace_id = (((current_setting('request.jwt.claims'::text, true))::json ->> 'workspace_id'::text))::bigint)); create policy "no_select" on "public"."services_connected" as restrictive for SELECT to anon using (false);
问题现象
即便((workspace_id = (((current_setting('request.jwt.claims'::text, true))::json ->> 'workspace_id'::text))::bigint))条件为真,anon用户也无法执行INSERT操作。
修正后的可用配置
create policy "no_select" on "public"."services_connected" for SELECT to anon using (false); create policy "workspace_insert_only" on "public"."services_connected" for insert to anon WITH CHECK ((workspace_id = (((current_setting('request.jwt.claims'::text, true))::json ->> 'workspace_id'::text))::bigint))
错误原因
最初的配置犯了两个关键错误:
- 误用
using子句处理INSERT操作:RLS中,using子句的作用是检查表中已存在的行是否满足权限条件,而INSERT是新增行,这个场景下没有已存在的行可以匹配using条件,直接返回false,导致操作被拦截。 - 用
for all策略覆盖所有操作不合理:INSERT操作的权限控制应该用WITH CHECK子句来验证新插入的行是否符合规则,而不是using。加上restrictive类型策略是叠加生效的,只要有一个restrictive策略不满足,操作就会被阻止,这里的for all策略直接给INSERT套了不适用的检查,自然失败。
修正后的配置拆分了操作类型,对INSERT单独使用WITH CHECK约束新行的合法性,同时保留禁止SELECT的策略,完美匹配需求。
内容的提问来源于stack exchange,提问作者Alwaysblue
相关产品推荐
相关产品推荐

