权限与 RLS 问题
权限问题常见表现为 permission denied、HTTP 401/403、查询返回空数组或写入失败。排查时需要同时检查角色授权和 RLS 策略。
判断问题类型
| 现象 | 优先排查 |
|---|---|
permission denied for table | 表权限、schema 权限 |
permission denied for sequence | 自增序列权限 |
| 查询成功但返回空数组 | RLS using 条件不匹配 |
| 插入或更新失败 | RLS with check 条件不匹配 |
| 未登录用户访问失败 | anon 角色或登录状态 |
检查表权限
select grantee, privilege_type
from information_schema.role_table_grants
where table_schema = 'public'
and table_name = 'todos'
order by grantee, privilege_type;
如果缺少权限,可按需授权:
grant usage on schema public to authenticated;
grant select, insert, update on public.todos to authenticated;
grant usage, select on all sequences in schema public to authenticated;
检查 RLS 状态
select schemaname, tablename, rowsecurity
from pg_tables
where schemaname = 'public'
and tablename = 'todos';
查看策略:
select policyname, cmd, roles, qual, with_check
from pg_policies
where schemaname = 'public'
and tablename = 'todos';
空结果排查
如果查询没有报错但返回空数组,通常是 RLS 条件过滤了所有行。检查:
- 当前用户是否已登录。
- 表中归属字段是否等于
auth.uid()。 - 策略是否使用了正确角色,例如
authenticated。 - 查询是否经过视图,且视图是否绕过 RLS。
select auth.uid();
auth.uid() 为 null 时,基于用户身份的策略会拒绝访问。
修复建议
- 前端直连表必须先设计 RLS,再开放表权限。
insert和update应同时检查WITH CHECK,避免用户写入他人数据。- 为 RLS 过滤字段创建索引,避免权限策略拖慢查询。
- 服务端管理操作建议走云函数或云托管,不要放宽前端 RLS。
详细策略示例请参考 基础权限。