必须手动验证PASSWORD_VERIFY_FUNCTION是否启用并有效,否则PROFILE修改无效;需查dba_profiles确认绑定、dba_objects验证函数状态及权限,并确保函数签名正确、建在SYS下且授PUBLIC执行权。

必须手动绑定并验证密码校验函数是否生效,否则改了 PROFILE 也白搭。
查当前 PASSWORD_VERIFY_FUNCTION 是否真启用
很多人执行了 ALTER PROFILE DEFAULT LIMIT PASSWORD_VERIFY_FUNCTION ORA12C_VERIFY_FUNCTION 就以为万事大吉,结果新密码还是能设成 oracle123。问题出在没确认函数是否真正挂载成功。
- 先查 profile 绑定:
SELECT limit FROM dba_profiles WHERE profile = 'DEFAULT' AND resource_name = 'PASSWORD_VERIFY_FUNCTION';—— 返回NULL或空值说明根本没启用 - 若返回函数名(如
ORA12C_VERIFY_FUNCTION),再查它是否存在且可用:SELECT owner, object_name, status FROM dba_objects WHERE object_name = 'ORA12C_VERIFY_FUNCTION' AND object_type = 'FUNCTION';——status必须是VALID,且owner是SYS - 函数存在但非
PUBLIC可执行?补上授权:GRANT EXECUTE ON ORA12C_VERIFY_FUNCTION TO PUBLIC;,否则普通用户改密时静默失败,只报模糊的ORA-28003
用 utlpwdmg.sql 创建函数 ≠ 策略自动生效
@?/rdbms/admin/utlpwdmg.sql 只干三件事:创建 ORA12C_VERIFY_FUNCTION、把 DEFAULT profile 的 PASSWORD_VERIFY_FUNCTION 设为该函数、设置部分默认参数。但它不处理两个关键断点:
- 已有用户可能绑的是其他 profile(比如
APP_PROFILE),查dba_users.profile才知道实际生效对象 - 脚本不会自动把用户从旧 profile 切换过去,
ALTER USER scott PROFILE DEFAULT;这步得自己补 - 字符集是
AL32UTF8时,函数对 Unicode 特殊字符(如中文标点)不校验,实际只按 ASCII 范围判断——别指望用「!@#」就能过,得用英文符号如!@#
自定义 verify_function 容易踩的硬坑
想加“禁止用户名拼音”或“禁用近三个月密码哈希”?手写函数时,以下三点错一个,ALTER USER ... IDENTIFIED BY 就直接报 ORA-28003 且无提示:
- 函数签名必须严格为:
FUNCTION my_verify (username IN VARCHAR2, password IN VARCHAR2, old_password IN VARCHAR2) RETURN BOOLEAN—— 多一个参数、少一个IN、返回NUMBER都会编译通过但运行失效 - 函数体内不能有
INSERT/UPDATE/DBMS_OUTPUT.PUT_LINE;调试只能靠RAISE_APPLICATION_ERROR抛错定位 - 函数必须建在
SYSschema 下,且创建后立刻GRANT EXECUTE ON my_verify TO PUBLIC;,否则调用时权限不足
静默安装时密码校验失败怎么办
dbca 静默建库卡在 password verification function is enabled,不是密码不够长,而是 DEFAULT profile 已启用校验函数,而响应文件里的密码不满足其规则(比如检查用户名倒序、字典词等)。最稳妥解法是在 runInstaller 前禁用:
- 连空实例:
sqlplus / as sysdba→startup nomount - 执行:
ALTER PROFILE DEFAULT LIMIT PASSWORD_VERIFY_FUNCTION NULL;—— 注意是NULL,不是'NULL'或空字符串 - 若已失败,先清理残留:
rm -rf $ORACLE_HOME/dbs/*和$ORACLE_BASE/oradata/*,再重试
真正容易被忽略的是:这个操作必须在数据库实例尚未创建前完成;一旦 dbca 开始建库,再进 SQL*Plus 就来不及了。











