ORA-28000表示账户已被Oracle主动锁定,非密码错误所致;需用DBA权限查dba_users中lock_date非空或account_status为LOCKED/LOCKED(TIMED)来确认,执行ALTER USER username ACCOUNT UNLOCK解锁,若同时过期还需重置密码。

查 LOCK_DATE 和 account_status 确认是否真被锁
ORA-28000 报错不等于密码错,而是账户状态已变。先用 DBA 权限执行:SELECT username, account_status, lock_date, expiry_date FROM dba_users WHERE username = 'YOUR_USER';。关键看两点:account_status 是否为 'LOCKED' 或 'LOCKED(TIMED)';lock_date 是否非空。若为空但状态含 LOCKED(TIMED),说明是失败登录超限后由 profile 自动触发,未记录具体时间点——这种更难追溯源头,需重点查审计或监听日志。
数据库审计开启时:直接查 dba_audit_session
如果 audit_trail 参数设为 DB 或 DB_EXTENDED(查 SHOW PARAMETER audit_trail 确认),且已对目标用户开启失败登录审计(AUDIT SESSION BY YOUR_USER WHENEVER NOT SUCCESSFUL;),就能准确定位 IP:SELECT userhost, terminal, spare1, comment$text FROM dba_audit_session WHERE username = 'YOUR_USER' AND returncode = 1017 ORDER BY timestamp DESC;。注意 comment$text 字段里常含完整客户端地址,例如 (HOST=10.113.27.15)(PORT=66453) ——这才是真实攻击源或配置错误源,别只盯着 userhost 看主机名。
审计关闭时:靠 listener.log 撞日志时间窗口
没开审计也不代表完全没线索。先用 ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'; 统一时间格式,查出 lock_date 精确到秒。然后去监听日志里捞匹配时间段的失败连接:grep -i "YOUR_USER" $ORACLE_HOME/diag/tnslsnr/*/listener/trace/listener.log | grep -i "refused\|failed\|1017" | grep -A 1 -B 1 "YYYY-MM-DD HH24:MI:SS"。注意不同 Oracle 版本日志路径可能含 hostname 或实例名,* 是安全通配。这个方法依赖日志滚动策略,若日志已被轮转或清理,就只能靠触发器补救了。
临时补漏:用触发器捕获实时失败登录
长期无审计又频繁被锁,可在 sys 下建触发器兜底:CREATE OR REPLACE TRIGGER log_failed_login AFTER SERVERERROR ON DATABASE BEGIN IF (IS_SERVERERROR(1017)) THEN INSERT INTO failed_login_log (username, ip, os_user, log_time) VALUES (SYS.LOGIN_USER, SYS_CONTEXT('USERENV','IP_ADDRESS'), SYS_CONTEXT('USERENV','OS_USER'), SYSDATE); END IF; END;。前提是已有表 failed_login_log 存储字段。该触发器不拦截登录,只记录,但会略微增加登录开销;上线前务必测试并发压力下性能影响。它解决的是“审计没开、日志已滚、问题还在发生”的中间态,不是替代方案。
lock_date 的精度和 listener.log 的保留周期往往决定你能回溯多远——很多环境默认只存 7 天日志,而锁定可能发生在密码变更后第三天,等你想到查日志,记录早已覆盖。


















