← 中文资源

简体中文版本

Supabase 行级安全策略

用行级安全策略锁死 Supabase 表访问:读写按 JWT 里的租户声明过滤,用户只能触碰自己租户的数据,服务角色单独放行。

阅读英文原文

示例说明

前端直连数据库的架构里,权限必须下沉到数据库层才可信——应用层过滤挡不住伪造请求。行级安全策略把 WHERE 条件写进策略:每条查询自动拼接租户断言,无租户匹配的行对查询者如同不存在。策略分动作定义:select 用 using 校验可见性,insert 与 update 还要 with check 校验写入值归属,防止把数据写进别人的租户。

技术要点

  • 策略从 JWT 声明提取租户身份
  • using 与 with check 分别校验读与写
  • 服务角色策略仅限维护通道

代码解读

四条策略覆盖选查、插入、更新与服务角色全权:读取要求行的租户等于令牌声明;插入与更新要求新值的租户同样匹配,防止越租户写入;service_role 的放行策略给后端维护任务留出通道,且应只授予受控的服务密钥持有者。

使用建议

启用 RLS 后无策略即默认全拒,先加策略再上线。服务密钥绝不能进入前端产物。策略性能受索引影响,tenant_id 要建索引。策略变更走迁移评审,它是安全边界本身。

代码示例

-- Supabase RLS policies:run at the Postgres layer
alter table projects enable row level security;

create policy "tenant read own projects"
  on projects for select
  using (tenant_id = auth.jwt() ->> 'tenant_id');

create policy "tenant insert own projects"
  on projects for insert
  with check (tenant_id = auth.jwt() ->> 'tenant_id');

create policy "tenant update own projects"
  on projects for update
  using (tenant_id = auth.jwt() ->> 'tenant_id')
  with check (tenant_id = auth.jwt() ->> 'tenant_id');

-- 服务端绕行角色仅在维护任务中使用
create policy "service role full access"
  on projects for all
  using (auth.role() = 'service_role');