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

APEX应用修改密码功能异常:旧密码校验始终不匹配

问题描述

我在APEX对象浏览器中有一张名为CSD_USERS的表,结构如下:

ID         NUMBER         
USERNAME     VARCHAR2(250)  
PASSWORD     VARCHAR2(15)   
ACCESS_TYPE  NUMBER 

注:PASSWORD字段已预先填充数据。

在共享组件\列表\列表详情中,我创建了名为Change Password的列表,其父列表条目设置为&APP_USER.。

我还创建了一个名为Change Password的页面,包含3个带PL/SQL代码验证的项:

  1. P14_OLD_PASSWORD的验证代码:
Declare
v_pass Varchar2(30);
Begin
  select PASSWORD into v_pass from CSD_USERS
    where ID = :APP_USER
    and Password = :P14_OLD_PASSWORD;

    RETURN TRUE;
    
    EXCEPTION
      WHEN OTHERS THEN
         RETURN FALSE;
end;
  1. P14_NEW_PASSWORD的验证代码:
BEGIN
IF 5 <= LENGTH(:P14_NEW_PASSWORD) AND  LENGTH(:P14_NEW_PASSWORD) <= 15  THEN
    IF REGEXP_LIKE(:P14_NEW_PASSWORD, '^.*[0-9]') THEN
 IF REGEXP_LIKE(:P14_NEW_PASSWORD, '^.*[a-z]', 'c') THEN
 IF REGEXP_LIKE(:P14_NEW_PASSWORD, '^.*[A-Z]', 'c') THEN
 IF REGEXP_LIKE(:P14_NEW_PASSWORD, '^.*[!@#$%^&*()_]', 'c') THEN
 RETURN '';
 ELSE
    RETURN 'Password must have a special character';
 END IF;
 ELSE
    RETURN 'Password must have at least one uppercase character';
 END IF;   
 ELSE
    RETURN 'Password must have at least one lowercase character';
 END IF;
 ELSE
    RETURN 'Password must have at least one numeric value';
 END IF; 
ELSE
RETURN 'Password length must be 5 or greater than 5
, Your password length is'||' '||LENGTH(:P14_NEW_PASSWORD);
END IF;
END;
  1. P14_RETYPE_NEW_PASSWORD_VALIDATION的验证规则:
V('P14_NEW_PASSWORD') = 
V('P14_RETYPE_NEW_PASSWORD')

该页面还有一个名为CHANGE_PASSWORD_PROCESS的流程,代码如下:

BEGIN
  UPDATE CSD_USERS
  SET PASSWORD = :P14_NEW_PASSWORD
  WHERE ID = :APP_USER
  AND PASSWORD = :P14_OLD_PASSWORD;
END;

问题:测试时,即使我复制/输入正确的旧密码,系统始终提示旧密码不匹配。请问导致登录用旧密码与修改时输入的旧密码对比失败的原因是什么?


问题分析与解决方向

以下是几种可能导致旧密码验证失败的核心原因:

  • :APP_USER 与表中ID字段不匹配
    APEX的:APP_USER默认存储的是用户登录的用户名(即表中USERNAME字段),但你的SQL语句中用ID = :APP_USER进行匹配。如果表中ID是数字类型,而:APP_USER是字符串类型的用户名,会直接导致类型转换错误或匹配无结果。应将条件改为USERNAME = :APP_USER,或确认:APP_USER确实存储的是用户的ID值。

  • 密码存储为加密/哈希值,而非明文
    若表中PASSWORD字段预先填充的是加密或哈希后的结果,而你输入的是明文旧密码,直接用Password = :P14_OLD_PASSWORD对比必然失败。需验证表中密码的存储形式,若为加密/哈希值,验证和更新流程都需要对输入的密码做相同的加密/哈希处理后再对比。

  • 输入项存在隐形空格
    输入的旧密码可能前后带有隐形空格,而表中存储的密码无空格。可在验证代码中对输入值做trim处理,修改查询条件为Password = TRIM(:P14_OLD_PASSWORD),同时检查页面项P14_OLD_PASSWORD是否开启自动去除空格的设置。

  • 异常捕获过于宽泛
    旧密码验证代码中WHEN OTHERS THEN RETURN FALSE会掩盖所有错误(比如:APP_USER匹配不到用户、类型转换错误等),导致任何错误都被判定为旧密码不匹配。建议修改为仅捕获NO_DATA_FOUND异常,其他异常抛出以方便排查:

    Declare
    v_pass Varchar2(30);
    Begin
      select PASSWORD into v_pass from CSD_USERS
        where ID = :APP_USER
        and Password = :P14_OLD_PASSWORD;
    
      RETURN TRUE;
      
      EXCEPTION
        WHEN NO_DATA_FOUND THEN
           RETURN FALSE;
        WHEN OTHERS THEN
           RAISE;
    end;
    
  • 大小写敏感差异
    新密码验证开启了大小写敏感,但旧密码查询默认遵循数据库的大小写敏感设置。若数据库参数NLS_COMP/NLS_SORT为大小写不敏感,但表中密码是大小写敏感存储,或反之,都会导致对比失败。可尝试显式指定大小写规则,比如UPPER(Password) = UPPER(:P14_OLD_PASSWORD)(若密码大小写不敏感)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 03:17:17