【问题标题】:Database Error Saving New User error with Postgres Function?使用 Postgres 函数保存新用户错误的数据库错误?
【发布时间】:2022-11-10 23:05:12
【问题描述】:

对于我的网站(由 Supabase 提供后端支持),我有内置的 auth.users 表和一个包含电子邮件、用户名和学校文本字段的 public.profiles 表。我创建了一个触发器和函数,当在auth.users 中插入新行时,将使用电子邮件作为电子邮件,将全名作为电子邮件的用户名组件(myName 用于myName@email.com)在 public.profiles 中插入一行, 并从 public.college_emails 表中查询大学名称以确定学校(如果某人使用域“@uci.edu”的电子邮件注册,它将在配置文件@987654326 中插入“加州大学欧文分校” @字段。如果无法匹配到学校的域,它将插入“其他”。

例子:

假设在我的网站上注册了电子邮件“rickAstley@ucla.edu”的用户。将此行添加到 auth.users 后,触发器应执行一个函数,该函数将使用以下字段向 public.profiles 添加新行:email:rickAstley@ucla.edu,full_name:rickAstley,school : 加州大学洛杉矶分校。

这是该函数的当前 Postgres 代码,由 auth.users 上的插入触发器执行:

create or replace function public.handle_new_user() 
returns trigger as $$
declare
  coll text ;
begin
  SELECT college
    INTO coll
    FROM college_emails 
  WHERE tag = SPLIT_PART(new.email, '@', 2);

  IF NOT FOUND
  THEN coll = 'Other' ;
  END IF ;

  INSERT INTO public.profiles (id, email, full_name, school, created_at)
  values (new.id, new.email, SPLIT_PART(new.email, '@', 1), coll, current_timestamp) ;
  return new;
end;
    
create trigger on_new_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();

当我使用虚构的 uuid 和学校电子邮件直接插入 auth.users 时,例如:

insert into auth.users (id, email) values ('d1d19367-3d0b-d497-9191-18a9d8e37850','myLongName@ucr.edu')

触发器和功能按预期完美执行。但是,如果我尝试以标准方式将用户添加到auth.users,通过以访客身份访问网站并注册,我会收到错误消息Database Error Saving New User.这是图像,尽管我怀疑它会有所帮助:

我不明白为什么这段代码在直接插入时可以正常工作,但在使用 Supabase 的 Auth 组件插入时却不行。这是创建注册功能的代码:

<Auth supabaseClient = {supabase} socialLayout = "horizontal" socialButtonSize = "xlarge" />

另一件需要注意的事情是当我使用一个函数时才不是在函数中执行查询,例如在第一个句点之前插入电子邮件域的第一部分而不是在public.college_emails中查找它,它工作正常(例如,使用域“@uci.edu”注册将插入“ uci" 进入school 字段,而不是查询全名)。

这就是工作功能:

create or replace function public.handle_new_user() 
returns trigger as $$
begin
  insert into public.profiles (id, email, full_name, school, created_at)
  values (new.id, new.email, SPLIT_PART(new.email, '@', 1), SPLIT_PART(new.email, '@', 2)
,current_timestamp);
  return new;
end;
$$ language plpgsql security definer;

我渴望在这个问题上的任何线索,非常感谢提前。

【问题讨论】:

  • 为什么不在 github 上的 supabase 讨论页面中提问?我面临着类似的问题。 :(

标签: sql postgresql authentication triggers supabase


【解决方案1】:

对于那些通过谷歌到达这里的人(就像我一样),这通常是由安全问题引起的。

默认情况下,PostgreSQL 函数定义为SECURITY INVOKER

这意味着该函数将以不同的用户身份执行,具体取决于它是由客户端 API 调用还是在 Supabase SQL 控制台中调用。

这就是为什么该功能可以在控制台而不是网站上工作的原因。

还有一点需要注意的是,当我使用的函数在函数中不执行查询时,比如在第一个句点之前插入电子邮件域的第一部分而不是在 public.college_emails 中查找,它工作正常

问题中显示的第二个示例由于以下行而起作用:

security definer

这会以定义它的用户身份执行该函数,因此无论从何处执行它都会成功。

将安全性更改为 definer 具有安全隐患。请注意 Supabase 文档中的以下警告:

最佳实践是使用安全调用程序(这也是默认设置)。如果您曾经使用安全定义器,则必须设置 search_path。如果您允许访问执行该功能的用户不应拥有的模式,这将限制潜在的损害。

有关详细信息,请参阅https://supabase.com/docs/guides/database/functions

另见 Github 问题中的相关讨论:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    • 2011-05-17
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多