如果说 Postgres 是港口主航道, 那 RLS,Row Level Security,就是港口里最关键的闸口制度。
Supabase 文档说得很直接:
- 对暴露给 API 的表,应该开启 RLS
- RLS 可以和 Supabase Auth 结合
- 这样浏览器到数据库的访问能形成端到端安全约束
你可以把它理解成:
不是只在港口大门查一次证,而是每一艘船、每一批货、每一道闸门都按规则决定能不能放行。
例如:
alter table public.projects enable row level security;
create policy "Users can view their own projects"
on public.projects
for select
to authenticated
using ((select auth.uid()) = owner_id);
create policy "Users can insert their own projects"
on public.projects
for insert
to authenticated
with check ((select auth.uid()) = owner_id);这套规则什么意思?
船主只能查看自己的货船
船主只能申报属于自己的货物这也是 Supabase 最容易让人“突然理解它”的瞬间。
因为你会意识到:
权限不一定非要全部写在中间层服务里,很多核心访问控制可以直接压进数据库关卡。
#RLS 的关键优势
- 权限离数据更近
- 浏览器直连时仍可受控
- 防止“绕过前端直接偷数据”
- 可与 JWT 身份联动
- 能形成数据库级 defense in depth
#RLS 的关键代价
- 你真的要会写策略
- 错误策略会导致数据泄露或全被拦死
- 性能也需要关注
- 复杂策略需要架构设计,不是随手补几条
Supabase 官方文档还特别强调了性能建议,比如:
- 不要乱把复杂逻辑塞进策略
- 谨慎处理 join
- 合理使用 security definer function
这说明一件事:
RLS 很强,但它不是魔法,它是一套严肃的港口关卡制度。