Oracle数据库密码过期问题终极解决方案:期限取消+用户解锁+原密码保留

在Oracle数据库使用过程中,"密码过期导致用户登录失败"是高频故障------默认情况下,Oracle的DEFAULT概要文件会设置密码有效期(通常180天),到期后用户会被限制登录,甚至批量用户过期会导致业务中断。

一、前置准备:登录数据库(必看)

所有操作需以 SYSDBA超级权限 登录(普通用户无权限修改配置和用户状态),推荐两种登录方式:

方式1:本地操作系统认证(推荐,无需数据库密码)

bash 复制代码
[oracle@localhost ~]$ sqlplus / as sysdba

# 成功登录提示
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

方式2:远程/密码认证(需知道SYS密码)

bash 复制代码
[oracle@localhost ~]$ sqlplus sys/你的SYS密码@数据库IP:端口/服务名 as sysdba

注意:若登录报错ORA-12154: TNS: 无法解析指定的连接标识符,需先检查tnsping服务名是否配置正确。

二、核心操作:从查询到解决( step by step )

1. 第一步:查询当前密码过期策略

先确认数据库默认的密码有效期配置,避免盲目修改:

sql 复制代码
-- 设置查询结果显示宽度(避免字段截断)
SQL> set lines 999
SQL> set pages 100
-- 查询DEFAULT概要文件的密码有效期
SQL> SELECT profile, resource_name, limit 
     FROM dba_profiles 
     WHERE profile='DEFAULT' 
       AND resource_name IN ('PASSWORD_LIFE_TIME', 'PASSWORD_GRACE_TIME');

结果说明:

  • PASSWORD_LIFE_TIME:密码有效期(示例中为180天,UNLIMITED表示无限制)
  • PASSWORD_GRACE_TIME:密码过期后的宽限期(宽限期内仍可登录,过期后锁定)
  • 若查询结果为空,说明DEFAULT概要文件未设置该参数,默认可能继承系统默认值(180天)

2. 第二步:取消密码期限限制(全局生效)

修改DEFAULT概要文件,让所有使用该配置的用户密码永不过期(生产环境最常用方案):

sql 复制代码
-- 取消密码有效期+宽限期限制
SQL> ALTER PROFILE DEFAULT LIMIT 
     PASSWORD_LIFE_TIME UNLIMITED  -- 密码永不过期
     PASSWORD_GRACE_TIME UNLIMITED; -- 取消宽限期(可选,避免弹窗提醒)

执行结果:

提示Profile altered.表示修改成功,即时生效(新创建的用户自动继承,已有用户无需额外配置)。

扩展:单独为某个用户设置策略(按需选择)

若不想全局修改DEFAULT策略,可创建自定义概要文件,仅应用于特定用户:

sql 复制代码
-- 1. 创建自定义概要文件(无密码过期限制)
CREATE PROFILE no_expire_profile LIMIT PASSWORD_LIFE_TIME UNLIMITED;

-- 2. 给目标用户分配该概要文件
ALTER USER SCOTT PROFILE no_expire_profile;

3. 第三步:排查过期/异常用户

修改策略后,需处理已过期的用户(策略修改不自动恢复已过期状态):

(1)查询所有过期用户(精准定位问题用户)

sql 复制代码
SQL> SELECT username, account_status, expiry_date 
     FROM dba_users 
     WHERE account_status LIKE 'EXPIRED%';

结果说明:

  • EXPIRED:密码已过期,无法登录
  • EXPIRED(GRACE):密码过期但仍在宽限期内,登录时会提示修改密码
  • 示例中SCOTT用户状态为EXPIRED,需优先处理

(2)查询所有用户状态(全面检查)

若需确认是否有"锁定+过期"的复合问题,执行:

sql 复制代码
SQL> SELECT username, account_status, expiry_date, profile 
     FROM dba_users 
     ORDER BY account_status;

结果说明:

可直观看到每个用户的:

  • 状态(是否过期/锁定)
  • 密码过期时间
  • 使用的概要文件(确认是否应用了DEFAULT策略)

4. 第四步:解锁被锁定的用户

若用户状态为LOCKED(密码错误次数过多导致),需先解锁(仅解锁账号,不解决密码过期):

sql 复制代码
-- 解锁单个用户(示例:SCOTT)
SQL> ALTER USER SCOTT ACCOUNT UNLOCK;

执行结果(如图5所示):

提示User altered.表示解锁成功。若需批量解锁,可拼接SQL:

sql 复制代码
-- 批量生成解锁SQL(复制结果执行)
SELECT 'ALTER USER ' || username || ' ACCOUNT UNLOCK;' 
FROM dba_users 
WHERE account_status LIKE 'LOCKED%';

5. 第五步:保留原密码,重置过期用户(核心需求)

最实用的场景:用户不想修改密码,仅需恢复过期状态。Oracle密码哈希存储在sys.user$表,通过提取哈希值可实现"重置密码但保留原密码"。

(1)查询用户密码哈希(确认存储位置)

sql 复制代码
-- 示例:查询SCOTT用户的密码哈希
SQL> SELECT name, spare4, password 
     FROM sys.user$ 
     WHERE name = 'SCOTT';

结果说明:

  • Oracle 12c+ 版本:密码哈希主要存储在spare4字段(格式为S:XXX
  • Oracle 11g及以下:密码哈希存储在password字段
  • 后续重置需拼接这两个字段(兼容新旧版本)

(2)批量生成「保留原密码」的重置SQL

无需手动拼接,直接执行以下SQL生成批量处理脚本:

sql 复制代码
SQL> SELECT 
       'ALTER USER ' || su.name || ' IDENTIFIED BY VALUES ''' 
       || su.spare4 || NVL(';' || su.password, '') || ''';' AS 重置脚本
     FROM sys.user$ su
     JOIN dba_users du 
       ON su.name = du.username 
       AND du.account_status LIKE 'EXPIRED%';

结果说明:

查询结果会生成针对每个过期用户的重置SQL,例如:
ALTER USER SCOTT IDENTIFIED BY VALUES 'S:XXX;XXX';

(3)执行生成的重置SQL

复制上一步输出的"重置脚本",批量执行:

sql 复制代码
-- 示例:执行SCOTT用户的重置SQL
SQL> ALTER USER SCOTT IDENTIFIED BY VALUES 'S:XXX;XXX';

执行结果:

提示User altered.表示成功,此时用户可使用原密码正常登录(密码过期状态已恢复)。

6. 第六步:手动修改密码(按需选择)

若需为用户设置新密码(而非保留原密码),直接执行:

sql 复制代码
-- 示例:修改CESHI用户密码为123456(需符合密码策略)
SQL> ALTER USER CESHI IDENTIFIED BY 123456;

注意:

  • 密码需符合当前概要文件的策略(如长度≥8位、包含字母+数字+特殊字符),否则会报错ORA-28003: 口令验证失败

  • 若需简化密码策略(生产环境不推荐),可修改DEFAULT概要文件:

    sql 复制代码
    ALTER PROFILE DEFAULT LIMIT 
      PASSWORD_MIN_LENGTH 6  -- 最小长度6位
      PASSWORD_COMPLEXITY 'NONE'; -- 取消复杂度要求

三、生产环境关键注意事项(避坑必看)

  1. 操作前备份 :修改DEFAULT概要文件或批量处理用户前,建议备份相关表:

    sql 复制代码
    CREATE TABLE dba_profiles_bak AS SELECT * FROM dba_profiles;
    CREATE TABLE dba_users_bak AS SELECT * FROM dba_users;
  2. 权限控制 :所有操作必须以SYSDBA身份执行,普通用户会提示ORA-01031: 权限不足

  3. 版本兼容性

    • 12c+ 版本必须使用spare4字段拼接,仅用password会导致密码失效。
    • 11g及以下版本无spare4字段,直接使用password字段即可。
  4. 批量操作测试 :批量处理前,先选择1个非核心用户(如SCOTT)测试流程,确认无问题后再推广。

  5. 定期检查 :建议每月执行一次过期用户查询,提前发现问题:

    sql 复制代码
    -- 定时任务查询脚本
    SELECT username, account_status, expiry_date 
    FROM dba_users 
    WHERE account_status LIKE 'EXPIRED%' 
    OR (expiry_date IS NOT NULL AND expiry_date < SYSDATE + 30); -- 提前30天预警

四、常见报错及解决方案

报错信息 原因 解决方案
ORA-01031: 权限不足 未以SYSDBA身份登录 重新执行sqlplus / as sysdba登录
ORA-28003: 口令验证失败 密码不符合当前概要文件策略 1. 按策略修改密码;2. 放宽密码策略(见步骤6)
ORA-01918: 用户不存在 用户名拼写错误(Oracle用户名区分大小写,默认大写) 执行SELECT username FROM dba_users;确认用户名
ORA-01940: 无法删除当前连接的用户 解锁/修改用户时,用户正在连接数据库 先kill会话:ALTER SYSTEM KILL SESSION 'sid,serial#';(sid/serial#从v$session查询)