示例说明
前端直连数据库的架构里,权限必须下沉到数据库层才可信——应用层过滤挡不住伪造请求。行级安全策略把 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');