已登录Supabase却无法向开启RLS的profiles表插入数据是什么原因?
问题原因
- 核心问题是调用
supabase.auth.signUp成功拿到返回的user对象时,Supabase客户端的auth会话还未完成同步更新,此时发起数据库插入请求携带的仍是未登录状态的匿名令牌,数据库执行RLS校验时auth.uid()返回值为null,和插入的id字段不匹配,触发规则校验失败。 - 如果项目开启了邮箱确认配置,用户注册成功后不会自动登录,客户端始终为匿名状态,也会触发相同报错。
解决方案
方案1:等待会话同步后执行插入
修改注册成功后的逻辑,先确认当前会话已生效再调用插入方法:
if(error){ alert("Error signing in"); } else { // 等待会话同步完成 const { data: { session } } = await supabase.auth.getSession() // 确认会话存在且用户ID匹配再执行插入 if(session && session.user.id === user.id) { await addUserDetails({ uuid: user.id, firstName: firstNameRef.current.value, lastName: lastNameRef.current.value }); navigate("/dashboard"); } }
如果开启了邮箱确认,不建议使用该方案,优先选方案2。
方案2:使用数据库触发器自动创建profile(更推荐)
在数据库层面创建触发器,当auth.users表新增用户时自动向public.profiles表插入初始化数据,完全避开前端会话同步问题,且触发器执行不触发RLS校验:
-- 创建触发器函数 create function public.handle_new_user() returns trigger as $$ begin insert into public.profiles (id, first_name, last_name) values (new.id, new.raw_user_meta_data->>'first_name', new.raw_user_meta_data->>'last_name'); return new; end; $$ language plpgsql security definer; -- 给auth.users表绑定插入触发器 create trigger on_auth_user_created after insert on auth.users for each row execute function public.handle_new_user();
使用该方案时需要把姓名参数传到signUp的options.data字段里,示例如下:
const {user, error} = await signUp({ email, password, options: { data: { first_name: firstNameRef.current.value, last_name: lastNameRef.current.value } } });
配置完成后可以删掉前端的addUserDetails调用,注册成功后直接跳转页面即可。
内容的提问来源于stack exchange,提问作者jm123456
相关产品推荐
相关产品推荐

