如何禁用Supabase读写权限,仅允许匿名/认证用户接收实时更新?
实现Supabase单向实时推送(无客户端读写权限)
核心思路
通过RLS规则严格限制普通用户的数据库操作权限,仅允许Supabase SERVICE_ROLE执行读写;同时配置Realtime组件的订阅权限,让客户端只能被动接收变更推送,无法直接与数据库交互。
1. 配置RLS规则,隔离客户端与服务端权限
先对目标表启用RLS,再创建两条核心规则:
-- 启用行级安全 ALTER TABLE your_target_table ENABLE ROW LEVEL SECURITY; -- 允许SERVICE_ROLE执行所有数据库操作 CREATE POLICY "Service role full access" ON your_target_table FOR ALL USING (current_role = 'service_role') WITH CHECK (current_role = 'service_role'); -- 拒绝所有普通用户(匿名/认证)的读写操作 CREATE POLICY "Deny regular user operations" ON your_target_table FOR ALL USING (false) WITH CHECK (false);
2. 配置Realtime订阅权限
在Supabase控制台完成以下设置:
- 进入「Realtime」面板,找到目标表并开启Realtime功能
- 在权限设置中,仅勾选「Subscribe」选项,取消所有读写权限
- 确保Realtime仅推送变更,不允许客户端触发任何数据库操作
3. 客户端仅订阅实现
客户端仅初始化Supabase并订阅变更,不执行任何读写请求:
import { createClient } from '@supabase/supabase-js'; const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY ); // 订阅表的所有变更事件 const updateChannel = supabase.channel('table-updates') .on('postgres_changes', { event: '*', schema: 'public', table: 'your_target_table' }, (payload) => { // 处理实时推送的变更数据 console.log('Received update:', payload); }) .subscribe(); // 注意:客户端执行任何读写操作都会被RLS规则拦截,比如: // supabase.from('your_target_table').select('*') // 会返回权限错误
4. 服务端用SERVICE_ROLE处理所有业务逻辑
所有数据库操作必须通过服务端(如Vercel函数)执行,使用SERVICE_ROLE_KEY绕过RLS限制:
import { createClient } from '@supabase/supabase-js'; const supabaseAdmin = createClient( process.env.SUPABASE_URL, process.env.SUPABASE_SERVICE_ROLE_KEY, { auth: { autoRefreshToken: false, persistSession: false } } ); export async function handler(req, res) { // 先完成业务逻辑处理(验证、数据转换等) const processedData = await validateAndTransform(req.body); // 用SERVICE_ROLE执行数据库操作 const { data, error } = await supabaseAdmin .from('your_target_table') .insert(processedData); if (error) return res.status(500).json({ error: error.message }); return res.status(200).json(data); }
关键注意事项
- 绝不向客户端暴露SERVICE_ROLE_KEY,仅使用ANON_KEY初始化客户端Supabase实例
- Realtime推送基于服务端主动发送,不受RLS的SELECT规则限制,只要控制台开启了订阅权限,客户端就能接收变更
- 如需按用户过滤推送内容,可在订阅时添加
filter参数,并调整RLS规则允许用户订阅自身相关行(仍拒绝直接查询)
内容的提问来源于stack exchange,提问作者Rutger Versteegden
相关产品推荐
相关产品推荐

