必须手动绑定函数并验证状态,否则PASSWORD_VERIFY_FUNCTION仍是NULL;查dba_profiles确认是否启用,再查dba_objects确保函数存在且STATUS为VALID,最后授PUBLIC执行权限。

必须手动绑定函数并验证状态,否则 PASSWORD_VERIFY_FUNCTION 仍是 NULL,所有弱密码都能通过。
怎么确认当前 profile 是否真启用了校验函数
别信“我执行过脚本了”,直接查。返回 NULL 就等于没开:
-
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 - 函数存在但没授权?非 SYS 用户改密会静默失败:
GRANT EXECUTE ON ORA12C_VERIFY_FUNCTION TO PUBLIC;
为什么执行了 @?/rdbms/admin/utlpwdmg.sql 还是设不出合规密码
脚本只创建函数、不自动写入 profile,也不影响已有自定义 profile。常见断点:
-
utlpwdmg.sql默认只修改DEFAULTprofile 的PASSWORD_VERIFY_FUNCTION字段,但如果你的用户绑的是SECURE_PROFILE,就得单独执行:ALTER PROFILE SECURE_PROFILE LIMIT PASSWORD_VERIFY_FUNCTION ORA12C_VERIFY_FUNCTION; - 函数创建后若字符集是
AL32UTF8,ORA12C_VERIFY_FUNCTION实际只校验 ASCII 范围内的特殊字符(仅_、$、#),中文标点或 emoji 会被忽略,看似满足“含特殊字符”实则无效 - 该函数强制禁止密码与用户名/实例名相同或倒序,也禁用纯数字、连续字符(如
12345678),但不会检查业务词典(如“admin”“test123”),这些得靠自定义函数补足
自定义 verify_function 最容易踩的三个硬坑
手写 PL/SQL 函数时,错一个就导致 ALTER USER ... IDENTIFIED BY 直接报 ORA-28003,且不提示具体哪条规则失败:
- 函数签名必须严格匹配:
FUNCTION your_func (username VARCHAR2, password VARCHAR2, old_password VARCHAR2) RETURN BOOLEAN,少一个参数或类型不对,调用时静默失败 - 函数体里不能有未处理的异常(如
SELECT ... INTO没NO_DATA_FOUND处理),否则抛错中断校验流程 - 函数必须在
SYSschema 下编译,且显式授予EXECUTE权限给PUBLIC;若放在其他 schema,即使GRANT了,profile 绑定时也会因权限路径问题失效
真正难的不是写函数,而是让函数被 profile 正确识别、被每个用户调用、且每次校验都给出可定位的反馈——Oracle 不会告诉你“密码含用户名拼音”,只会说“验证失败”。


















