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

Supabase中用户仅读写自有数据的配置及数据库函数权限疑问

关于Supabase行级策略与数据库函数的权限问题解答

1. 配置的Select策略是否限制登录用户仅查看自己的任务?

是的,你配置的这个select策略可以实现仅允许已认证(authenticated)用户读取自己的任务:

create policy "Anonymous and permanent users can read their own tasks only"
on public.tasks
for select to authenticated
using ((select auth.uid()) = user_id);

需要注意的是,策略名称里提到了匿名用户,但to authenticated指定了仅对已登录用户生效,匿名用户(未登录)会被拒绝访问tasks表的select操作。如果需要允许匿名用户有特定权限,需要单独配置针对anon角色的策略。

2. 数据库函数是否需要传入user_id参数?

不需要传入user_id参数,直接使用第二个不带参数的函数即可:

create or replace function get_tasks_without_date()
returns setof tasks
language plpgsql
as $$
begin
  return query select * from tasks where date is null;
end;
$$;

原因是:PostgreSQL函数默认使用SECURITY INVOKER(调用者权限),执行函数时会沿用调用者的权限上下文,包括已生效的行级策略。也就是说,当已登录用户调用这个函数时,tasks表的select策略会自动生效,过滤出user_id = auth.uid()的行,再加上函数里的date is null条件,最终返回的就是该用户的无日期任务。

如果手动传入user_id并在函数里加条件,虽然也能实现效果,但属于冗余操作,还可能增加权限漏洞的风险(比如传入不属于自己的user_id)。

3. 调用函数时用户ID如何传递给Supabase?

当你在Android应用中使用已登录的supabaseClient调用RPC函数时:

supabaseClient.postgrest.rpc(
    function = "get_tasks_without_date").decodeList<Task>()

客户端会自动在请求头中携带当前登录用户的JWT令牌,PostgREST服务会解析这个令牌,提取用户ID并设置auth.uid()函数的返回值。行级策略中的auth.uid()就是从这里获取当前用户的ID,从而自动完成数据过滤。

安全拉取及修改数据的建议

  • 覆盖所有操作的行级策略:除了select,还要为update、delete操作配置对应的策略,确保用户只能修改/删除自己的任务。例如:

    -- Update策略
    create policy "Users can update their own tasks"
    on public.tasks
    for update to authenticated
    using (auth.uid() = user_id)
    with check (auth.uid() = user_id);
    
    -- Delete策略
    create policy "Users can delete their own tasks"
    on public.tasks
    for delete to authenticated
    using (auth.uid() = user_id);
    

    with check用于验证更新后的数据仍符合权限条件,防止用户将任务的user_id改为他人ID。

  • 关闭表的默认公共权限:执行以下语句撤销public角色对tasks表的所有权限,确保只有通过行级策略授权的用户能访问数据:

    revoke all on public.tasks from public;
    
  • 谨慎使用SECURITY DEFINER函数:如果你的函数需要使用更高权限,不得不设置SECURITY DEFINER,一定要限制函数的执行权限,避免被滥用。同时要避免在这类函数中直接处理用户输入,防止注入攻击。

  • 验证客户端输入:在insert/update操作中,通过行级策略的with check条件或数据库约束,确保用户无法插入不属于自己的user_id数据。例如在tasks表中设置user_id为不可空,并默认值为auth.uid()(仅对已认证用户生效):

    alter table public.tasks alter column user_id set default auth.uid();
    
  • 依赖Supabase Auth管理用户:不要自行实现登录逻辑,使用Supabase提供的Auth SDK管理用户会话,确保只有合法的已认证用户能访问需要权限的资源。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 10:04:59