因SELECT的RLS策略导致Supabase Update操作失败的问题排查
问题:Supabase RLS中SELECT策略为何会影响UPDATE操作?
我有一张Account(id, status, owner)表,配置了以下RLS策略:
SELECT策略
CREATE POLICY "Allow users to select active accounts" ON "public"."Account" AS PERMISSIVE FOR SELECT TO public USING ((owner = auth.uid()) AND (status = 'active'))
UPDATE策略
CREATE POLICY "Allow users to update their own accounts" ON "public"."Account" AS PERMISSIVE FOR UPDATE TO public USING ((owner = auth.uid())) WITH CHECK ((owner = auth.uid()))
SELECT操作正常,但使用最新版JS SDK执行以下代码将记录的status更新为deleted时,出现RLS违规错误:
await supabase.from("Account").update({"status":"deleted"}).eq('id', id)
若移除SELECT策略中的AND (status = 'active')条件,更新操作即可正常执行。我并未在更新时主动执行查询,且默认应返回最少数据,不理解为何SELECT策略会影响更新,请问忽略了什么?
原因与解决方案
核心原因
Supabase JS SDK的update方法默认会返回更新后的行数据,这个返回过程会触发SELECT策略的检查。当你把账号状态改为deleted后,该行数据不再满足SELECT策略中status = 'active'的条件,因此在返回数据时触发RLS权限违规。
解决方案
方案1:禁止返回更新后的行
如果不需要获取更新后的结果,可以在update调用末尾添加.select(''),明确指定不返回任何字段,这样就不会触发SELECT策略:
await supabase.from("Account").update({"status":"deleted"}).eq('id', id).select('')
方案2:调整SELECT策略(按需选择)
如果需要返回更新后的行,同时允许用户查看自己所有状态的账号,可以修改SELECT策略,去掉status = 'active'的限制:
CREATE POLICY "Allow users to select their own accounts" ON "public"."Account" AS PERMISSIVE FOR SELECT TO public USING ((owner = auth.uid()))
方案3:添加更精细的SELECT策略(复杂场景)
如果既要保留"仅查看active账号"的默认SELECT权限,又要允许查看自己删除的账号,可以新增一个优先级更高的SELECT策略:
CREATE POLICY "Allow users to view their own deleted accounts" ON "public"."Account" AS PERMISSIVE FOR SELECT TO public USING ((owner = auth.uid()) AND (status = 'deleted'))
RLS会合并所有PERMISSIVE策略的条件,这样用户既能查看自己的active账号,也能查看自己删除的账号,更新后返回数据就不会触发违规。
内容的提问来源于stack exchange,提问作者byteSlayer
相关产品推荐
相关产品推荐

