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

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;

排查方向及解决方案

  1. 权限检查

    • 确保APEX应用的解析模式用户拥有USERS表的SELECT权限,以及authenticate_user函数的EXECUTE权限,执行以下授权语句:
      GRANT SELECT ON USERS TO [你的解析模式用户];
      GRANT EXECUTE ON authenticate_user TO [你的解析模式用户];
      
  2. 函数参数匹配

    • APEX自定义认证函数的参数名必须严格为p_username和p_password,检查函数定义是否完全匹配(包括大小写,避免特殊场景下的不兼容)。
  3. 密码一致性验证

    • 确认登录页面的密码项已设置为「Password」类型,避免明文传递时被转义或截断。
    • 检查USERS表中存储的密码是否为明文(当前函数为明文匹配,若页面密码默认加密传递则会不匹配),需调整函数逻辑匹配APEX的密码处理规则。
  4. 认证架构配置细节

    • 进入「Shared Components > Authentication Schemes > 自定义认证架构」:
      • 确认「Authentication Function」字段填写完整的函数路径(含Schema前缀,如[schema].authenticate_user)。
      • 检查「Session Validation Function」是否正确配置,未设置时可复用authenticate_user或使用默认验证逻辑。
      • 确认「User Identification > Username Attribute」设置为USERNAME(与表中字段名一致)。
  5. 运行时调试

    • 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。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 13:43:14