Oracle 19c中用户密码过期后,需先查清其绑定PROFILE及EXPIRY_DATE状态,再用ALTER USER ... IDENTIFIED BY VALUES 'SPARE4值'可无明文恢复原密码;PROFILE修改(如PASSWORD_LIFE_TIME UNLIMITED)即时生效但不自动更新已过期用户的expiry_date,必须显式重置密码才解锁。
oracle 19c 中用户密码过期后,alter user ... identified by 能重置密码,但若应用依赖原密码、又无法获取明文,直接改密会导致连接中断;真正关键的不是“怎么输命令”,而是“改完是否生效”“是否触发新策略校验”“老密码还能不能用”。
查清用户当前绑定的 PROFILE 和实际过期状态
很多操作失败,是因为没确认两件事:用户到底绑的是哪个 PROFILE,以及 EXPIRY_DATE 字段是不是真已过期(或为 NULL)。不查就改,容易白忙活。
-
SELECT username, profile, account_status, expiry_date FROM dba_users WHERE username = 'SCOTT';—— 看状态是否为EXPIRED或EXPIRED(GRACE),expiry_date是否早于SYSDATE -
SELECT resource_name, limit FROM dba_profiles WHERE profile = 'YOUR_PROFILE' AND resource_type = 'PASSWORD';—— 特别注意PASSWORD_LIFE_TIME是UNLIMITED还是数字,PASSWORD_VERIFY_FUNCTION是否启用(它会强制复杂度校验) - 如果用户绑的是自定义
PROFILE,改DEFAULT没用;如果account_status是LOCKED,光改密码也不行,得先ALTER USER ... ACCOUNT UNLOCK
用 IDENTIFIED BY VALUES 保留原密码(无需明文)
当应用配置里写死的是密文、运维不知道原密码、又不敢动连接串时,IDENTIFIED BY VALUES 是唯一稳妥方案。它跳过所有密码复杂度校验,直接还原哈希值。
- Oracle 19c 的密码哈希存在
sys.user$.SPARE4字段(11g/12c 是PASSWORD字段),查法:SELECT name, SPARE4 FROM sys.user$ WHERE name = 'SCOTT'; - 执行重置:
ALTER USER scott IDENTIFIED BY VALUES 'S:3BF46B2AC692CD7CD80082CB6C7C4B1C323F8A0CE044F1B477ADE2BE807E';—— 注意S:前缀不能丢,这是 19c 的 SHA-2 标识 - 如果只拿到旧密码的 16 进制哈希(如
F894844C34402B67),那是 11g 风格,19c 下直接用会报ORA-01017: invalid username/password;必须用SPARE4值
ALTER USER IDENTIFIED BY 触发密码复杂度校验的坑
只要目标 PROFILE 启用了 PASSWORD_VERIFY_FUNCTION(比如默认的 ORA12C_STRONG_VERIFY),用 IDENTIFIED BY 就会校验长度、大小写、数字、特殊字符——哪怕你只是想设回原来那个“弱密码”。
- 常见报错:
ORA-28003: password verification for the specified password failed - 临时绕过方法(需 DBA 权限):
ALTER PROFILE your_profile LIMIT PASSWORD_VERIFY_FUNCTION NULL;,改完再恢复(不推荐长期禁用) - 更安全的做法:先用
IDENTIFIED BY VALUES恢复登录,再让应用方按策略生成新密码,最后用IDENTIFIED BY正式更新 - 注意:
IDENTIFIED BY会重算EXPIRY_DATE,而IDENTIFIED BY VALUES不会——后者只是“解锁”,原过期时间仍保留(除非 PROFILE 已设为UNLIMITED)
改完密码后仍连不上?检查连接池和客户端缓存
命令执行成功、dba_users 显示状态正常,但应用还是报 ORA-28001: the password has expired,大概率不是数据库问题,而是中间层卡住了。
- Tomcat / WebLogic 等连接池常缓存认证上下文,重启数据源或整个应用服务才能刷新
- JDBC URL 加了
?oracle.jdbc.thin.forceConnectionReset=true可强制重连(仅限较新驱动) - SQL*Plus 或 SQL Developer 如果之前连过该用户,可能还拿着旧 session,关掉重开
- 特别注意:如果数据库启用了
SEC_CASE_SENSITIVE_LOGON=TRUE(12c+ 默认),而应用传的是小写密码,也会模拟“过期失败”现象,实际是大小写不匹配
最易被忽略的一点:已有用户的 EXPIRY_DATE 不会因 PROFILE 修改自动更新。哪怕你把 PASSWORD_LIFE_TIME 改成 UNLIMITED,一个早已过期的用户仍处于 EXPIRED 状态,必须显式执行一次 ALTER USER ... IDENTIFIED BY 或 IDENTIFIED BY VALUES 才能解除锁定。


















