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 |
问题原因
auth.uid()无有效上下文:函数中使用auth.uid()获取当前用户ID,但如果函数在未认证的环境下执行(比如直接在SQL编辑器中调用函数,而非通过Supabase客户端的认证接口调用),auth.uid()会返回NULL,导致where id = NULL的条件永远不成立,查询无结果触发not found异常。- 错误提示误导:原函数未区分“用户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
相关产品推荐
相关产品推荐

