Supabase触发器函数权限问题:触发器调用函数时访问被拒绝
解决Supabase触发器调用函数时的权限拒绝问题
问题原因
PostgreSQL函数默认采用SECURITY INVOKER执行模式,即函数会以调用者的权限运行。你的触发器由supabase_auth_admin用户触发,因此public.handle_new_user()会以该用户的权限执行操作:
supabase_auth_admin没有public.profiles表的插入权限,也没有调用public.insert_into_profiles()函数的足够权限- 你直接执行函数时用的是
postgres用户(Supabase的超级用户),拥有所有操作权限,因此不会出现权限问题
解决方案
将public.handle_new_user()或public.insert_into_profiles()设置为SECURITY DEFINER模式,让函数以其拥有者的权限执行(默认拥有者是postgres,具备所需权限)。同时需要设置安全的搜索路径,避免SQL注入风险。
修改handle_new_user()函数
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users; CREATE OR REPLACE FUNCTION public.handle_new_user() RETURNS TRIGGER AS $$ BEGIN RAISE LOG 'Current user: %', current_user; PERFORM public.insert_into_profiles( NEW.id, (NEW.raw_user_meta_data->>'first_name'), (NEW.raw_user_meta_data->>'last_name') ); RETURN NEW; END; $$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = public; -- 限制搜索路径,提升安全性 CREATE TRIGGER on_auth_user_created AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
(可选)修改insert_into_profiles()函数
如果不想修改触发器函数,也可以直接调整insert_into_profiles()的执行模式:
CREATE OR REPLACE FUNCTION public.insert_into_profiles(user_id uuid, first_name text, last_name text) RETURNS void AS $$ BEGIN INSERT INTO public.profiles(id, first_name, last_name) VALUES(user_id, first_name, last_name); END; $$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = public;
额外验证
修改完成后,创建新用户触发触发器,检查public.profiles表是否成功插入数据,同时查看日志确认函数执行的用户已切换为函数拥有者(postgres)。
内容的提问来源于stack exchange,提问作者Joerie
相关产品推荐
相关产品推荐

