查清用户绑定的PROFILE和EXPIRY_DATE状态是前提:先查dba_users确认ACCOUNT_STATUS及EXPIRY_DATE是否过期,再查dba_profiles中PASSWORD_LIFE_TIME和PASSWORD_VERIFY_FUNCTION设置;ALTER PROFILE仅影响新用户,已过期者须ALTER USER重置密码或用IDENTIFIED BY VALUES恢复原密。

查清用户当前绑定的 PROFILE 和 expiry_date 状态
不查就改,大概率白忙活。很多操作失败,是因为没确认两件事:用户到底绑的是哪个 PROFILE,以及 EXPIRY_DATE 字段是不是真已过期(或为 NULL)。
用 DBA 权限执行:
SELECT username, profile, account_status, expiry_date FROM dba_users WHERE username = 'SCOTT';
重点看:ACCOUNT_STATUS 是否为 EXPIRED 或 EXPIRED(GRACE);EXPIRY_DATE 是否早于 SYSDATE(或为 NULL)。
再查对应 profile 的密码策略:
SELECT resource_name, limit FROM dba_profiles WHERE profile = 'DEFAULT' AND resource_type = 'PASSWORD';
特别关注 PASSWORD_LIFE_TIME 是数字还是 UNLIMITED,以及 PASSWORD_VERIFY_FUNCTION 是否启用——它会强制复杂度校验,影响后续改密操作。
ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED 立即生效但不修复已过期用户
这是最常用、也最有效的全局解法。命令本身即时生效,但只影响后续认证行为,不会回溯更新已有用户的 EXPIRY_DATE。
-
UNLIMITED是关键字,不能加引号;写成'UNLIMITED'会报ORA-00922 - 修改后,新创建的用户自动继承该策略;但已过期用户仍无法登录,必须单独重置密码
- 如果用户绑定的是自定义 profile(如
APP_PROFILE),要把DEFAULT换成对应名称 - 中间件(如 Tomcat JDBC 连接池)可能缓存旧连接,导致现象延迟,不是命令没生效
ALTER USER ... IDENTIFIED BY VALUES 可无明文恢复原密码
当应用配置里硬编码的是密文、你不知道原密码明文、又不敢动连接串时,这是唯一安全方案。它跳过所有密码复杂度校验,直接写入哈希值。
Oracle 19c 的密码哈希存在 sys.user$.SPARE4 字段,带 S: 前缀:
SELECT name, SPARE4 FROM sys.user$ WHERE name = 'SCOTT';
拿到值后执行:
ALTER USER scott IDENTIFIED BY VALUES 'S:3BF46B2AC692CD7CD80082CB6C7C4B1C323F8A0CE044F1B477ADE2BE807E';
注意:S: 前缀不能丢,否则报 ORA-01017;若只拿到旧密码的 16 进制哈希(如 F894844C34402B67),那是 11g 风格,19c 下直接用会失败。
ORA-28002 提示只是预警,ALTER USER IDENTIFIED BY 才能清除
ORA-28002 是密码到期前 7 天的安全提示,不影响登录,但必须处理——忽略会导致后续出现 ORA-28001(真正无法登录)。
只有 ALTER USER ... IDENTIFIED BY 能清除该提示,改 PROFILE 或 UNLOCK 都无效。
- 即使新密码和旧密码完全一样,也能消除警告(前提是未启用密码历史策略)
- 若用户状态是
EXPIRED(GRACE),需先执行ALTER USER ... ACCOUNT UNLOCK再改密 - 执行后,
EXPIRY_DATE会重置为SYSDATE + PASSWORD_LIFE_TIME
真正关键的不是“怎么输命令”,而是“改完是否生效”“是否触发新策略校验”“老密码还能不能用”。尤其是 PASSWORD_VERIFY_FUNCTION 启用后,哪怕设回原密码,也可能因不符合复杂度被拒——这时候就得用 IDENTIFIED BY VALUES 绕过校验。


















