Supabase RLS策略报错‘stack depth limit exceeded’求助
解决RLS策略触发"stack depth limit exceeded"无限递归问题
问题根源
你的is_member_of函数会查询启用了RLS的user_profiles表,而RLS策略又调用这个函数。当执行查询时:
- 查询
user_profiles触发RLS检查 - RLS策略调用
is_member_of函数 - 函数再次查询
user_profiles,又触发RLS检查 - 循环往复导致栈溢出
其他项目能正常运行,大概率是因为函数或RLS配置存在差异(比如函数绕过了RLS、表未启用RLS等)。
解决方案
方案1:查询时直接绕过RLS
修改函数,在查询user_profiles时使用WITH BYPASSRLS关键字,跳过RLS检查:
create or replace function is_member_of(_user_id uuid, _role_id bigint) returns boolean as $$ SELECT EXISTS ( SELECT 1 FROM user_profiles om WITH BYPASSRLS WHERE om.role_id = _role_id AND om.user_id = _user_id ); $$ language sql stable;
方案2:使用SECURITY DEFINER临时关闭RLS
通过SECURITY DEFINER让函数以创建者权限执行,并临时关闭RLS:
create or replace function is_member_of(_user_id uuid, _role_id bigint) returns boolean as $$ BEGIN SET LOCAL row_security = off; RETURN EXISTS ( SELECT 1 FROM user_profiles om WHERE om.role_id = _role_id AND om.user_id = _user_id ); END; $$ language plpgsql security definer stable; -- 限制函数执行权限,仅授权给需要的用户(比如你的应用认证用户) REVOKE ALL ON FUNCTION is_member_of(uuid, bigint) FROM PUBLIC; GRANT EXECUTE ON FUNCTION is_member_of(uuid, bigint) TO authenticated;
验证RLS策略
确保你的RLS策略逻辑正确,比如允许匹配指定角色的用户访问全表:
-- 先启用RLS(如果还没启用) ALTER TABLE user_profile ENABLE ROW LEVEL SECURITY; -- 创建全表访问策略 CREATE POLICY "Full access for matched role" ON user_profile FOR ALL USING (is_member_of(auth.uid(), 1)); -- 替换1为你需要授权的role_id
注意事项
- 函数需标记为
stable,让PostgreSQL可以缓存结果,减少重复执行 - 使用
SECURITY DEFINER时,务必限制函数执行权限,避免安全风险 - 确认
auth.uid()能正确获取当前用户的UUID(适用于Supabase等使用auth.users的场景)
内容的提问来源于stack exchange,提问作者Viperboy
相关产品推荐
相关产品推荐

