Supabase实时RLS配置:基于唯一URL限制数据删改权限
实现无登录下基于唯一链接的Supabase行权限控制
核心思路
借助Supabase的行级安全(RLS)+ 会话变量传递edit_link参数,同时确保实时订阅也严格遵循权限规则。
步骤1:开启表的RLS
先给boards表启用行级安全,禁用默认的全表访问权限:
ALTER TABLE boards ENABLE ROW LEVEL SECURITY; DROP POLICY IF EXISTS "Allow all access to boards" ON boards;
步骤2:创建会话变量与RLS策略
注册一个自定义会话变量,再编写针对匿名用户的更新、删除策略,仅允许操作edit_link匹配会话变量的行:
-- 注册自定义会话变量(仅需执行一次) ALTER ROLE anon SET app.current_edit_link = ''; -- 创建更新策略:限制仅能修改匹配edit_link的行,且不允许修改edit_link本身 CREATE POLICY "Allow update only for matching edit_link" ON boards FOR UPDATE TO anon USING (edit_link = current_setting('app.current_edit_link', true)::text) WITH CHECK (edit_link = current_setting('app.current_edit_link', true)::text); -- 创建删除策略:仅能删除匹配edit_link的行 CREATE POLICY "Allow delete only for matching edit_link" ON boards FOR DELETE TO anon USING (edit_link = current_setting('app.current_edit_link', true)::text);
USING控制哪些行可被选中操作,WITH CHECK确保更新后的数据仍符合权限规则,防止用户篡改edit_link。
步骤3:客户端传递edit_link参数
在用户访问/edit/xyz页面时,先通过RPC调用设置会话变量,后续所有操作(更新、删除、实时订阅)都会自动遵守RLS规则:
// 客户端JS代码示例 const editLink = window.location.pathname.split('/')[2]; // 从URL中提取xyz // 先调用RPC设置会话变量 await supabase.rpc('set_current_edit_link', { link: editLink }); // 执行更新操作(eq条件可省略,RLS会自动过滤) await supabase .from('boards') .update({ title: '更新后的标题' }) .eq('edit_link', editLink); // 实时订阅:仅会收到匹配当前edit_link的行变更 const subscription = supabase .channel('board_updates') .on('postgres_changes', { event: '*', schema: 'public', table: 'boards' }, (payload) => console.log('行变更:', payload) ) .subscribe();
对应的RPC函数需提前创建:
CREATE OR REPLACE FUNCTION set_current_edit_link(link text) RETURNS void AS $$ BEGIN PERFORM set_config('app.current_edit_link', link, true); END; $$ LANGUAGE plpgsql SECURITY DEFINER; -- 给匿名用户授予执行该函数的权限 GRANT EXECUTE ON FUNCTION set_current_edit_link(text) TO anon;
SECURITY DEFINER确保匿名用户能通过函数修改会话变量(匿名用户本身无直接调用set_config的权限)。
实时场景注意事项
- 订阅会自动应用RLS策略,只要提前设置好会话变量,只会收到符合当前
edit_link的行变更。 - 页面刷新后需重新调用RPC设置会话变量,因为会话变量绑定在当前连接上。
额外安全加固
- 确保
edit_link是足够随机的长字符串(比如用gen_random_uuid()生成),避免被暴力猜解。 - 给
boards表的edit_link列添加唯一约束,防止重复:
ALTER TABLE boards ADD CONSTRAINT unique_edit_link UNIQUE (edit_link);
内容的提问来源于stack exchange,提问作者AndersD
相关产品推荐
相关产品推荐

