You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

撤销Postgres的SELECT权限后RLS失效,请求排查问题

问题原因及解决方法

核心问题1:RLS策略的USING与WITH CHECK未区分

你创建的workspace_only策略用了for all,但仅提供了using子句——这个子句仅控制读取/修改时的行可见性(比如SELECT能看到哪些行、DELETE/UPDATE能操作哪些行),但对于INSERT操作,必须添加with check子句验证新插入的行是否符合规则,否则INSERT会被RLS拦截。

核心问题2:权限撤销与RLS策略冲突

你执行了REVOKE SELECT ON services_connected FROM anon;,同时策略包含for all(覆盖SELECT),导致:

  • SELECT操作直接被权限拒绝(即使RLS允许也无效)
  • 其他操作(INSERT/UPDATE/DELETE)虽可能保留权限,但RLS的using子句需要调用者能看到对应行才能操作,而anon无SELECT权限,无法验证行可见性,最终操作被拒。

核心问题3:函数执行上下文权限不足

你的disconnect_service函数默认是SECURITY INVOKER(以调用者anon的权限执行),但anon缺少services_connected和users_list表的DELETE权限,同时RLS策略未明确允许anon执行DELETE操作。


修复步骤

1. 调整基础权限

先确保anon拥有非SELECT操作的权限:

GRANT INSERT, UPDATE, DELETE ON services_connected TO anon;
GRANT INSERT, UPDATE, DELETE ON users_list TO anon;

2. 拆分RLS策略,精准控制操作

删除原有的for all策略,分别为不同操作创建针对性策略:

-- 删除原有策略
DROP POLICY "workspace_only" ON public.services_connected;

-- 允许anon操作自己工作区的行(UPDATE/DELETE)
CREATE POLICY "allow_workspace_delete_update"
ON public.services_connected
FOR UPDATE, DELETE
TO anon
USING ((workspace_id = ((current_setting('request.jwt.claims'::text, true))::json ->> 'workspace_id'::text)::bigint));

-- 允许anon插入自己工作区的行(INSERT)
CREATE POLICY "allow_workspace_insert"
ON public.services_connected
FOR INSERT
TO anon
WITH CHECK ((workspace_id = ((current_setting('request.jwt.claims'::text, true))::json ->> 'workspace_id'::text)::bigint));

3. 优化函数权限上下文(可选更安全方案)

如果不想给anon直接操作表的权限,可将函数设为SECURITY DEFINER(以函数拥有者权限执行),仅开放函数调用权限:

DROP FUNCTION IF EXISTS public.disconnect_service;

CREATE OR REPLACE FUNCTION public.disconnect_service(service_name_value TEXT)
RETURNS VOID AS $$
DECLARE
  workspace_id_value BIGINT := ((current_setting('request.jwt.claims'::text, TRUE))::JSON ->> 'workspace_id')::BIGINT;
BEGIN
  DELETE from services_connected where workspace_id = workspace_id_value and service_name = service_name_value;
  DELETE FROM users_list WHERE workspace_id = workspace_id_value and service_name = service_name_value; 
END;
$$ LANGUAGE plpgsql SECURITY DEFINER
SET search_path = public;

-- 仅允许anon调用该函数
GRANT EXECUTE ON FUNCTION public.disconnect_service(TEXT) TO anon;

内容的提问来源于stack exchange,提问作者Alwaysblue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 05:32:44