You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Supabase自定义check_password函数持续抛出'not found'异常求助

Supabase check_password 函数抛出“not found ”异常排查与修复

问题场景

编写了一个Supabase函数check_password,用于验证当前登录用户输入的密码是否与自身存储的密码匹配,但函数始终抛出not found <NULL>异常。在SQL编辑器中使用固定用户ID执行相同逻辑的查询语句,能正常返回匹配结果。

原函数代码:

drop function if exists "public"."check_password"(email text, passwd text);

set check_function_bodies = off;

CREATE OR REPLACE FUNCTION public.check_password(passwd text)
 RETURNS boolean
 LANGUAGE plpgsql
AS $function$declare
_uid uuid; -- for checking by 'is not found'
begin
if (passwd = '') then
  raise exception 'Password cannot be empty';
end if;

select id into _uid
from auth.users
where id = auth.uid()
and encrypted_password = crypt(passwd::text, auth.users.encrypted_password);

if not found then
  raise exception 'not found %', _uid;
end if;

return true;
end;$function$
;

SQL编辑器中可正常执行的验证语句:

select id
from auth.users
where id = '3829daea-4144-4d1a-9642-234ba35d7d2b'
and encrypted_password = crypt('password', auth.users.encrypted_password);

查询结果:

id
3829daea-4144-4d1a-9642-234ba35d7d2b

问题原因

  1. auth.uid() 无有效上下文:函数中使用auth.uid()获取当前用户ID,但如果函数在未认证的环境下执行(比如直接在SQL编辑器中调用函数,而非通过Supabase客户端的认证接口调用),auth.uid()会返回NULL,导致where id = NULL的条件永远不成立,查询无结果触发not found异常。
  2. 错误提示误导:原函数未区分“用户ID不存在”和“密码不匹配”两种情况,统一抛出not found,导致无法快速定位问题根源。

修复方案

1. 确保函数在认证上下文执行

必须通过Supabase客户端的rpc方法调用该函数,且调用前用户已完成登录认证。例如(JavaScript示例):

const { data, error } = await supabase.rpc('check_password', { passwd: 'user-input-password' });

直接在SQL编辑器中测试时,需先手动设置用户上下文:

set role authenticated;
set request.jwt.claim.sub = '3829daea-4144-4d1a-9642-234ba35d7d2b';
select check_password('password');

2. 优化函数逻辑与错误提示

修改函数,先检查auth.uid()是否为NULL,并区分用户不存在和密码不匹配的错误:

drop function if exists "public"."check_password"(passwd text);

set check_function_bodies = off;

CREATE OR REPLACE FUNCTION public.check_password(passwd text)
 RETURNS boolean
 LANGUAGE plpgsql
 SECURITY DEFINER -- 若执行角色无auth.users访问权限可添加,注意权限控制
AS $function$
declare
  _encrypted_pwd text;
begin
  if passwd = '' then
    raise exception 'Password cannot be empty';
  end if;

  -- 检查是否有已认证用户
  if auth.uid() is null then
    raise exception 'No authenticated user found';
  end if;

  -- 获取当前用户的加密密码
  select encrypted_password into _encrypted_pwd
  from auth.users
  where id = auth.uid();

  if not found then
    raise exception 'User not found';
  end if;

  -- 验证密码匹配
  if crypt(passwd::text, _encrypted_pwd) != _encrypted_pwd then
    raise exception 'Invalid password';
  end if;

  return true;
end;$function$
;

修改说明:

  • 新增auth.uid()非空检查,提前抛出未认证的明确错误。
  • 拆分查询与验证逻辑,分别处理“用户不存在”和“密码错误”的场景。
  • 可选添加SECURITY DEFINER:解决函数执行角色无auth.users表访问权限的问题,需注意权限边界避免安全风险。

内容的提问来源于stack exchange,提问作者Yura

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:15:59