PostgreSQL 15中pgjwt签名函数调用报错问题排查
问题原因与解决方法
这个问题的核心是参数类型不匹配:pgjwt提供的sign函数接受的第一个参数类型是json或jsonb,而你动态构建payload时,大概率直接生成了text类型的字符串,PostgreSQL无法自动隐式转换该类型去匹配sign函数的参数要求,因此抛出“函数不存在”的错误;硬编码场景下你可能显式声明了json/jsonb类型(比如用::json强制转换),所以能正常运行。
解决步骤
确保动态payload为json/jsonb类型
错误示例(动态拼接字符串生成text类型payload):CREATE OR REPLACE FUNCTION generate_jwt(p_role text, p_secret text) RETURNS text AS $$ DECLARE v_payload text; BEGIN v_payload := '{"sub": "' || p_role || '", "exp": ' || extract(epoch from now() + interval '1 hour') || '}'; RETURN pgjwt.sign(v_payload, p_secret); -- text类型参数不匹配 END; $$ LANGUAGE plpgsql;正确写法(用
json_build_object直接生成json类型):CREATE OR REPLACE FUNCTION generate_jwt(p_role text, p_secret text) RETURNS text AS $$ DECLARE v_payload json; BEGIN v_payload := json_build_object( 'sub', p_role, 'exp', extract(epoch from now() + interval '1 hour') ); RETURN pgjwt.sign(v_payload, p_secret); END; $$ LANGUAGE plpgsql;若坚持字符串拼接,必须强制转换类型:
v_payload := ('{"sub": "' || p_role || '", "exp": ' || extract(epoch from now() + interval '1 hour') || '}')::json;验证函数签名匹配
执行以下命令查看pgjwt的sign函数参数类型:SELECT proname, proargtypes::regtype[] FROM pg_proc WHERE proname = 'sign' AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pgjwt');结果会显示它的参数为
json, text或jsonb, text,需确保第一个参数是这两种类型之一。规避SQL注入风险
禁止用字符串拼接方式构建payload,这会引入注入隐患。使用json_build_object/jsonb_build_object既能保证类型正确,又能安全生成JSON对象。
内容的提问来源于stack exchange,提问作者ziazo
相关产品推荐
相关产品推荐

