必须创建专用profile并设password_life_time为unlimited,绑定服务账号;仅重置密码或修改default profile无法根治ora-28002/28001,因策略生效依赖用户实际绑定的profile而非默认值。

直接结论:不能靠“定期改密码”来避免,必须从 profile 策略层切断 password_life_time 的生效逻辑。
查清账号当前绑定的 profile 和 password_life_time 实际值
很多运维误以为改了密码就一劳永逸,结果一周后又收到 ORA-28002,根本原因是没确认策略源头。必须用 DBA 权限执行:
SELECT username, profile, account_status, expiry_date FROM dba_users WHERE username = 'SERVICE_USER';
再查该 profile 的真实限制:
SELECT resource_name, limit FROM dba_profiles WHERE profile = 'DEFAULT' AND resource_name = 'PASSWORD_LIFE_TIME';
- 如果
limit是数字(如180),说明策略在生效 - 如果返回空行,Oracle 会按内部默认值(通常是 180)处理,不是“没设”而是“没显式覆盖”
-
expiry_date为NULL表示从未触发过密码策略计算,但不等于永不过期——下次ALTER USER ... IDENTIFIED BY就会写入新值
生产环境推荐方案:为服务账号单独建无过期 profile
全局改 DEFAULT profile 风险高,尤其当数据库里混着开发、测试、应用账号时。更稳妥的做法是隔离策略:
- 创建专用 profile:
CREATE PROFILE svc_no_expire LIMIT PASSWORD_LIFE_TIME UNLIMITED; - 绑定到服务账号:
ALTER USER SERVICE_USER PROFILE svc_no_expire; - 验证是否生效:
SELECT profile FROM dba_users WHERE username = 'SERVICE_USER';必须返回svc_no_expire
注意:已有用户的 expiry_date 不会自动清零,但后续登录不再受该字段约束——Oracle 只校验当前 profile 的 PASSWORD_LIFE_TIME,而非历史日期。
为什么 ALTER USER IDENTIFIED BY 不能替代 profile 调整
单纯执行 ALTER USER SERVICE_USER IDENTIFIED BY xxx 只是重置密码并更新 expiry_date,但不会改变策略本身。7 天后照样触发 ORA-28002,180 天后必然 ORA-28001。
- 它只是把
expiry_date设为SYSDATE + PASSWORD_LIFE_TIME,而这个加数仍由 profile 决定 - 若 profile 中
PASSWORD_LIFE_TIME是180,那每次改密只是把倒计时重置为 180 天,不是取消倒计时 - 想“保留原密码哈希”?用
IDENTIFIED BY VALUES,但前提是先解决策略问题,否则哈希恢复后依然会过期
容易被忽略的宽限期(PASSWORD_GRACE_TIME)影响
即使设了 UNLIMITED,如果 profile 里 PASSWORD_GRACE_TIME 是非零值(比如默认 7),用户在 expiry_date 到期后仍能登录 7 天——这段时间内 Oracle 会持续报 ORA-28002,且连接成功后立即提示“Your password will expire in X days”。这会让监控误判、日志污染,也暴露安全风险。
- 务必同步清理:
ALTER PROFILE svc_no_expire LIMIT PASSWORD_GRACE_TIME 0; - 不要依赖
ACCOUNT UNLOCK:那是应对LOCKED状态的,和密码过期无关 - 检查状态字段:
account_status为OPEN才算真正干净;EXPIRED(GRACE)表示已进入宽限期,必须等策略生效或改密才能退出











