oracle无法仅靠password_life_time强制改密,也无法单靠profile参数实现密码复杂度,必须搭配password_verify_function;该函数需先通过utlpwdmg.sql脚本创建并绑定到profile才生效,否则alter profile设置无效;已有用户expiry_date不会随profile修改自动更新,须手动执行alter user ... identified by replace或用户登录触发重算。
直接说结论:oracle 里没法靠 password_life_time 单独实现“强制改密”,也没法靠 profile 自带参数实现密码复杂度——必须搭配 password_verify_function 才行;而且这个函数必须先存在,否则设了也白设。
为什么 ALTER PROFILE ... LIMIT PASSWORD_VERIFY_FUNCTION xxx 不生效
常见错误是直接执行 ALTER PROFILE DEFAULT LIMIT PASSWORD_VERIFY_FUNCTION verify_function_11G,但数据库里根本没这个函数。Oracle 自带的验证函数(如 VERIFY_FUNCTION_11G)默认不启用,需要手动安装脚本。
- 检查函数是否存在:
SELECT object_name, status FROM dba_objects WHERE object_name IN ('VERIFY_FUNCTION', 'VERIFY_FUNCTION_11G') AND owner = 'SYS'; - 若不存在,用 SYS 登录后运行:
@?/rdbms/admin/utlpwdmg.sql(注意路径可能因 Oracle 版本/安装路径不同而变化) - 该脚本会创建
VERIFY_FUNCTION_11G,并设为默认验证函数;也可自定义函数,但必须满足签名要求(3 个VARCHAR2参数,返回BOOLEAN) - 函数创建后,
PASSWORD_VERIFY_FUNCTION才真正起作用;否则用户仍可设123456这类弱密码,且不会报错
设置密码有效期时,expiry_date 不更新怎么办
这是最常被忽略的坑:Profile 修改后,已有用户的 expiry_date 字段不会自动重算。哪怕你把 PASSWORD_LIFE_TIME 改成 90,昨天刚改过密的用户,expiry_date 还是按旧策略推算的日期。
- 查当前过期时间:
SELECT username, expiry_date, password_last_changed FROM dba_users WHERE username = 'YOUR_USER'; - 只有两种方式能刷新
expiry_date:- 用户自己登录触发强制改密(前提是策略已生效)
- DBA 手动执行:
ALTER USER your_user IDENTIFIED BY current_password REPLACE current_password;(相当于“重设但不变”,会重置计时起点)
- 别指望
ALTER PROFILE后跑个命令就全局刷新——Oracle 不提供这种批量重算机制
PASSWORD_REUSE_TIME 和 PASSWORD_REUSE_MAX 怎么配合才防得住“换汤不换药”
只设 PASSWORD_LIFE_TIME,用户可能循环用 3 个密码来回切;这两个参数才是真防复用的关键,但它们是“或”关系,不是“与”关系。
-
PASSWORD_REUSE_TIME 365:表示 365 天内不能重用任何历史密码 -
PASSWORD_REUSE_MAX 10:表示至少要换满 10 次新密码,才能再次使用某个旧密码 - 只要满足任一条件,就允许复用——所以建议同时设,比如都设成 365 和 10,实际效果是“一年内且至少换 10 次后才可复用”
- 注意:
PASSWORD_HISTORY只记录通过ALTER USER ... IDENTIFIED BY或登录强制改密产生的密码;DBA 用IDENTIFIED BY VALUES直接设哈希值,不会写入历史,也就绕过了复用限制
真正麻烦的是验证函数和历史密码记录这两块——前者要手动装脚本、后者依赖用户行为触发更新,都不是改个 Profile 就一劳永逸的事。











