Oracle APEX自定义登录认证失败:合法数据遭拒问题排查
Oracle APEX自定义登录认证失败问题排查
我在Oracle APEX中实现自定义登录功能时,合法登录数据持续被拒绝。具体情况:
- 已创建
USERS表,表结构见下方代码 - 编写了
authenticate_user自定义认证函数,在APEX SQL命令控制台测试时能得到预期结果 - 配置「Custom」类型的自定义认证架构后,应用仍无法正常登录,参考教程操作后问题依旧
- 附自定义认证架构及应用认证配置截图(原提问含截图,此处文字说明)
USERS表结构
CREATE TABLE "USERS" ( "USER_ID" NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE, "USERNAME" VARCHAR2(100) NOT NULL ENABLE, "PASSWORD" VARCHAR2(512) NOT NULL ENABLE, "IS_ADMIN" VARCHAR2(1) NOT NULL ENABLE, CONSTRAINT "PK_CUSTOM_USERS" PRIMARY KEY ("USER_ID") USING INDEX ENABLE, CONSTRAINT "UQ_CUSTOM_USERS_USERNAME" UNIQUE ("USERNAME") USING INDEX ENABLE ) ;
authenticate_user认证函数
create or replace FUNCTION authenticate_user (p_username VARCHAR2, p_password VARCHAR2) RETURN BOOLEAN IS l_count NUMBER; BEGIN -- 调试语句:输出输入参数 DBMS_OUTPUT.PUT_LINE('Input Username: ' || p_username); DBMS_OUTPUT.PUT_LINE('Input Password: ' || p_password); -- 查询用户名和密码是否匹配 SELECT COUNT(*) INTO l_count FROM USERS WHERE USERNAME = p_username AND PASSWORD = p_password; -- 调试语句:输出匹配计数 DBMS_OUTPUT.PUT_LINE('Count: ' || l_count); -- 判断是否匹配成功 IF l_count > 0 THEN RETURN TRUE; -- 认证成功 ELSE RETURN FALSE; -- 认证失败 END IF; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM); RETURN FALSE; -- 任何错误都返回认证失败 END;
测试代码(SQL命令控制台执行正常)
DECLARE v_username VARCHAR2(100) := 'tommy'; v_password VARCHAR2(100) := 'password'; v_is_valid BOOLEAN; BEGIN v_is_valid := authenticate_user(v_username, v_password); IF v_is_valid THEN DBMS_OUTPUT.PUT_LINE('Authentication successful'); ELSE DBMS_OUTPUT.PUT_LINE('Authentication failed'); END IF; END;
排查方向及解决方案
权限检查
- 确保APEX应用的解析模式用户拥有
USERS表的SELECT权限,以及authenticate_user函数的EXECUTE权限,执行以下授权语句:GRANT SELECT ON USERS TO [你的解析模式用户]; GRANT EXECUTE ON authenticate_user TO [你的解析模式用户];
- 确保APEX应用的解析模式用户拥有
函数参数匹配
- APEX自定义认证函数的参数名必须严格为
p_username和p_password,检查函数定义是否完全匹配(包括大小写,避免特殊场景下的不兼容)。
- APEX自定义认证函数的参数名必须严格为
密码一致性验证
- 确认登录页面的密码项已设置为「Password」类型,避免明文传递时被转义或截断。
- 检查
USERS表中存储的密码是否为明文(当前函数为明文匹配,若页面密码默认加密传递则会不匹配),需调整函数逻辑匹配APEX的密码处理规则。
认证架构配置细节
- 进入「Shared Components > Authentication Schemes > 自定义认证架构」:
- 确认「Authentication Function」字段填写完整的函数路径(含Schema前缀,如
[schema].authenticate_user)。 - 检查「Session Validation Function」是否正确配置,未设置时可复用
authenticate_user或使用默认验证逻辑。 - 确认「User Identification > Username Attribute」设置为
USERNAME(与表中字段名一致)。
- 确认「Authentication Function」字段填写完整的函数路径(含Schema前缀,如
- 进入「Shared Components > Authentication Schemes > 自定义认证架构」:
运行时调试
- APEX运行时不会输出
DBMS_OUTPUT内容,可修改函数将调试信息写入日志表:-- 先创建日志表 CREATE TABLE AUTH_DEBUG_LOG ( LOG_TIMESTAMP TIMESTAMP DEFAULT SYSTIMESTAMP, USERNAME VARCHAR2(100), PASSWORD VARCHAR2(512), MATCH_COUNT NUMBER, ERROR_MSG VARCHAR2(2000) ); -- 修改后的认证函数 create or replace FUNCTION authenticate_user (p_username VARCHAR2, p_password VARCHAR2) RETURN BOOLEAN IS l_count NUMBER; BEGIN INSERT INTO AUTH_DEBUG_LOG (USERNAME, PASSWORD) VALUES (p_username, p_password); COMMIT; SELECT COUNT(*) INTO l_count FROM USERS WHERE USERNAME = p_username AND PASSWORD = p_password; UPDATE AUTH_DEBUG_LOG SET MATCH_COUNT = l_count WHERE LOG_TIMESTAMP = SYSTIMESTAMP; COMMIT; RETURN l_count > 0; EXCEPTION WHEN OTHERS THEN UPDATE AUTH_DEBUG_LOG SET ERROR_MSG = SQLERRM WHERE LOG_TIMESTAMP = SYSTIMESTAMP; COMMIT; RETURN FALSE; END; - 尝试登录后查询
AUTH_DEBUG_LOG表,查看传递的用户名、密码是否正确,以及匹配计数是否为0。
- APEX运行时不会输出
内容的提问来源于stack exchange,提问作者Dev Yego
相关产品推荐
相关产品推荐

