Supabase中不同角色权限与单一匿名密钥的权限管控疑问
解决方案:Supabase无登录场景下的权限分离方案
1. 核心思路:RLS+自定义角色(无需完整Supabase Auth)
不用启用用户登录系统,通过**行级安全(RLS)**结合自定义数据库角色,就能区分写入端(Node.js)和只读端(SvelteKit)的权限,既规避服务密钥的安全风险,又实现权限隔离。
2. 具体操作步骤
数据库表权限配置
- 先给元数据表开启RLS(必须先做,否则默认权限会绕过策略):
ALTER TABLE your_metadata_table ENABLE ROW LEVEL SECURITY;
- 给匿名角色(
anon)配置只读策略:
CREATE POLICY "Anonymous read-only access" ON your_metadata_table FOR SELECT USING (true);
- 创建自定义写入角色(比如
doc_writer),并配置全权限策略:
-- 创建角色 CREATE ROLE doc_writer WITH LOGIN PASSWORD 'your_strong_password'; -- 给角色分配表权限 GRANT SELECT, INSERT, UPDATE, DELETE ON your_metadata_table TO doc_writer; -- 创建RLS策略限定该角色的操作 CREATE POLICY "Writer role full access" ON your_metadata_table FOR ALL USING (current_user = 'doc_writer');
Storage权限配置
在Supabase控制台的Storage页面,找到目标bucket:
- 给
anon角色添加只读权限(勾选select、download) - 给
doc_writer角色添加读写权限(勾选insert、update、delete、download)
客户端配置
Node.js写入端
不用服务密钥,用自定义角色的凭证初始化客户端:
import { createClient } from '@supabase/supabase-js'; const supabase = createClient( 'https://your-project.supabase.co', null, { auth: { autoRefreshToken: false, persistSession: false }, global: { headers: { 'Authorization': `Bearer ${your_custom_jwt}` } } } );
注:自定义JWT可在Supabase控制台「API」页面生成,确保JWT的role字段设为doc_writer,密钥用项目的JWT_SECRET签发
SvelteKit只读端
保持用匿名密钥初始化客户端即可,因为RLS已经限制了该角色仅能读数据。
3. 安全风险规避
- 绝对不要把服务密钥暴露在任何公开代码中,仅用于Supabase内部管理操作。
- 所有生产环境的表必须强制开启RLS,哪怕是内部使用的表,避免默认权限漏洞。
- RLS策略要精准:写入权限严格绑定自定义角色,不要用
USING (true)这种宽松条件;如果有数据隔离需求,还可以添加行级过滤(比如仅允许修改自己写入的元数据)。
4. 关于默认权限的说明
Supabase默认未开RLS时允许全量CRUD确实需要警惕,但只要给所有表开启RLS并配置严格策略,就能完全控制资源访问,覆盖绝大多数安全场景,不用过度担忧。
内容的提问来源于stack exchange,提问作者Kvetoslav
相关产品推荐
相关产品推荐

