Skip to content

Oracle 密码策略与管理

密码策略是Oracle数据库安全体系的第一道防线,合理的密码策略可以有效防止弱密码攻击、暴力破解和密码泄露等安全风险。对于DBA而言,掌握密码策略的配置、管理和最佳实践是保障数据库安全的基本要求。

密码策略基础

核心概念

密码策略通过Profile对象实现,包含以下关键要素:

  • 密码复杂度:定义密码必须包含的字符类型和长度
  • 密码有效期:密码的有效使用时间,过期后需更换
  • 密码宽限期:密码过期后允许继续使用的 grace 时间
  • 密码历史记录:防止用户重复使用近期密码
  • 密码锁定:连续错误登录尝试后的账号锁定机制
  • 密码验证函数:用于验证密码是否符合复杂度要求

Profile 机制

Profile是Oracle数据库中用于定义用户资源限制和密码限制的对象:

  • 每个用户必须分配一个Profile,默认使用DEFAULT Profile
  • 支持为不同用户群体创建不同的Profile(如管理员、普通用户、应用用户)
  • 在多租户环境中,每个PDB可以有独立的Profile配置
  • 支持动态修改,修改后立即生效于所有关联用户

密码策略配置

查看现有Profile

sql
-- 查看所有Profile
SELECT DISTINCT PROFILE FROM DBA_PROFILES;

-- 查看DEFAULT Profile的密码策略
SELECT RESOURCE_NAME, RESOURCE_TYPE, LIMIT 
FROM DBA_PROFILES 
WHERE PROFILE = 'DEFAULT' AND RESOURCE_TYPE = 'PASSWORD';

-- 查看用户所属的Profile
SELECT USERNAME, PROFILE, ACCOUNT_STATUS 
FROM DBA_USERS 
WHERE ACCOUNT_STATUS NOT IN ('EXPIRED & LOCKED', 'LOCKED');

配置密码复杂度

使用内置验证函数

Oracle 12c及以上版本提供了两个内置的密码验证函数:

sql
-- 查看可用的密码验证函数
SELECT OBJECT_NAME 
FROM ALL_OBJECTS 
WHERE OBJECT_TYPE = 'FUNCTION' AND OBJECT_NAME LIKE '%VERIFY_FUNCTION%';

-- 启用强密码验证(推荐生产环境使用)
ALTER PROFILE DEFAULT LIMIT 
  PASSWORD_VERIFY_FUNCTION ora12c_strong_verify_function;

-- 启用基本密码验证(适合测试环境)
ALTER PROFILE DEFAULT LIMIT 
  PASSWORD_VERIFY_FUNCTION ora12c_verify_function;

密码复杂度参数配置

sql
-- 设置密码最小长度为12位
ALTER PROFILE DEFAULT LIMIT PASSWORD_MIN_LENGTH 12;

-- 设置密码必须包含的字符类型(通过验证函数实现)
-- ora12c_strong_verify_function要求:大小写字母+数字+特殊字符

配置密码有效期和宽限期

sql
-- 配置管理员密码策略(更严格)
CREATE PROFILE admin_profile LIMIT
  PASSWORD_LIFE_TIME 30           -- 密码有效期30天
  PASSWORD_GRACE_TIME 5           -- 宽限期5天
  PASSWORD_REUSE_TIME 365         -- 1年内不能重复使用
  PASSWORD_REUSE_MAX 20           -- 不能使用最近20个密码
  FAILED_LOGIN_ATTEMPTS 3         -- 3次错误尝试后锁定
  PASSWORD_LOCK_TIME 24           -- 锁定24小时
  PASSWORD_MIN_LENGTH 14          -- 最小14位
  PASSWORD_VERIFY_FUNCTION ora12c_strong_verify_function;

-- 配置应用用户密码策略
CREATE PROFILE app_profile LIMIT
  PASSWORD_LIFE_TIME 90           -- 密码有效期90天
  PASSWORD_GRACE_TIME 7           -- 宽限期7天
  PASSWORD_REUSE_TIME 180         -- 6个月内不能重复使用
  PASSWORD_REUSE_MAX 10           -- 不能使用最近10个密码
  FAILED_LOGIN_ATTEMPTS 5         -- 5次错误尝试后锁定
  PASSWORD_LOCK_TIME 12           -- 锁定12小时
  PASSWORD_MIN_LENGTH 12          -- 最小12位
  PASSWORD_VERIFY_FUNCTION ora12c_strong_verify_function;

-- 配置只读用户密码策略(较宽松)
CREATE PROFILE readonly_profile LIMIT
  PASSWORD_LIFE_TIME 180          -- 密码有效期180天
  PASSWORD_GRACE_TIME 14          -- 宽限期14天
  PASSWORD_REUSE_TIME 90          -- 3个月内不能重复使用
  PASSWORD_REUSE_MAX 5            -- 不能使用最近5个密码
  FAILED_LOGIN_ATTEMPTS 10        -- 10次错误尝试后锁定
  PASSWORD_LOCK_TIME 6            -- 锁定6小时
  PASSWORD_MIN_LENGTH 10          -- 最小10位
  PASSWORD_VERIFY_FUNCTION ora12c_verify_function;

密码锁定策略配置

sql
-- 设置连续错误尝试次数和锁定时间
ALTER PROFILE DEFAULT LIMIT
  FAILED_LOGIN_ATTEMPTS 5
  PASSWORD_LOCK_TIME 1;

-- 配置永久锁定(需要手动解锁)
ALTER PROFILE admin_profile LIMIT
  FAILED_LOGIN_ATTEMPTS 3
  PASSWORD_LOCK_TIME UNLIMITED;

密码验证函数

内置验证函数对比

函数名称适用版本复杂度要求推荐场景
verify_function_11gOracle 11g8位+大小写字母+数字+特殊字符11g升级环境
ora12c_verify_functionOracle 12c+8位+大小写字母+数字测试环境
ora12c_strong_verify_functionOracle 12c+12位+大小写字母+数字+特殊字符生产环境

自定义密码验证函数

对于特殊安全要求,可以创建自定义密码验证函数:

sql
CREATE OR REPLACE FUNCTION custom_password_verify(
  username VARCHAR2,
  password VARCHAR2,
  old_password VARCHAR2
) RETURN BOOLEAN IS
  invalid_pwd EXCEPTION;
BEGIN
  -- 密码长度检查:至少12位
  IF LENGTH(password) < 12 THEN
    RAISE_APPLICATION_ERROR(-20001, '密码长度必须至少为12位');
  END IF;
  
  -- 字符类型检查:必须包含大小写字母、数字和特殊字符
  IF NOT REGEXP_LIKE(password, '[A-Z]') THEN
    RAISE_APPLICATION_ERROR(-20002, '密码必须包含至少一个大写字母');
  END IF;
  
  IF NOT REGEXP_LIKE(password, '[a-z]') THEN
    RAISE_APPLICATION_ERROR(-20003, '密码必须包含至少一个小写字母');
  END IF;
  
  IF NOT REGEXP_LIKE(password, '[0-9]') THEN
    RAISE_APPLICATION_ERROR(-20004, '密码必须包含至少一个数字');
  END IF;
  
  IF NOT REGEXP_LIKE(password, '[^A-Za-z0-9]') THEN
    RAISE_APPLICATION_ERROR(-20005, '密码必须包含至少一个特殊字符');
  END IF;
  
  -- 不能包含用户名
  IF INSTR(UPPER(password), UPPER(username)) > 0 THEN
    RAISE_APPLICATION_ERROR(-20006, '密码不能包含用户名');
  END IF;
  
  -- 不能包含连续3个或以上相同字符
  IF REGEXP_LIKE(password, '(.)\1{2,}') THEN
    RAISE_APPLICATION_ERROR(-20007, '密码不能包含3个或以上连续相同字符');
  END IF;
  
  -- 不能包含常见弱密码模式
  IF REGEXP_LIKE(LOWER(password), 'password|admin|oracle|123456|qwerty') THEN
    RAISE_APPLICATION_ERROR(-20008, '密码不能使用常见弱密码模式');
  END IF;
  
  RETURN TRUE;
END;
/

-- 编译并使用自定义验证函数
ALTER FUNCTION custom_password_verify COMPILE;

ALTER PROFILE strong_profile LIMIT
  PASSWORD_VERIFY_FUNCTION custom_password_verify;

密码管理操作

密码重置与修改

sql
-- DBA重置用户密码
ALTER USER app_user IDENTIFIED BY "StrongPass_2023";

-- 重置密码并解锁用户
ALTER USER locked_user IDENTIFIED BY "NewPass_2023" ACCOUNT UNLOCK;

-- 用户自行修改密码
ALTER USER app_user IDENTIFIED BY "NewPass_2023" REPLACE "OldPass_2023";

-- 使用SQL*Plus PASSWORD命令
PASSWORD
Changing password for APP_USER
Old password: ********
New password: ********
Retype new password: ********
Password changed

用户锁定与解锁

sql
-- 手动锁定用户
ALTER USER temp_user ACCOUNT LOCK;

-- 手动解锁用户
ALTER USER temp_user ACCOUNT UNLOCK;

-- 锁定用户并设置解锁时间
ALTER USER temp_user ACCOUNT LOCK UNTIL '2023-12-31 23:59:59';

-- 查看锁定的用户
SELECT USERNAME, ACCOUNT_STATUS, LOCK_DATE 
FROM DBA_USERS 
WHERE ACCOUNT_STATUS LIKE '%LOCKED%';

密码过期管理

sql
-- 手动设置密码过期
ALTER USER app_user PASSWORD EXPIRE;

-- 查看密码即将过期的用户
SELECT USERNAME, PROFILE, 
       TRUNC(EXPIRY_DATE) AS EXPIRE_DATE, 
       TRUNC(EXPIRY_DATE) - SYSDATE AS DAYS_LEFT
FROM DBA_USERS
WHERE EXPIRY_DATE IS NOT NULL 
  AND TRUNC(EXPIRY_DATE) - SYSDATE <= 7  -- 7天内过期
ORDER BY DAYS_LEFT;

-- 批量重置即将过期的用户密码(示例)
DECLARE
  CURSOR expiring_users IS
    SELECT USERNAME FROM DBA_USERS
    WHERE EXPIRY_DATE <= SYSDATE + 7;
BEGIN
  FOR u IN expiring_users LOOP
    -- 这里应该使用更安全的密码生成方式
    EXECUTE IMMEDIATE 'ALTER USER ' || u.USERNAME || ' IDENTIFIED BY "TempPass_' || TO_CHAR(SYSDATE, 'YYYYMMDD') || '" PASSWORD EXPIRE';
    DBMS_OUTPUT.PUT_LINE('重置用户 ' || u.USERNAME || ' 密码并设置为过期');
  END LOOP;
END;
/

多租户环境密码管理

CDB与PDB Profile

在多租户环境中,密码策略可以在CDB和PDB级别分别配置:

sql
-- 在CDB$ROOT中创建通用Profile
CREATE ROLE c##common_role CONTAINER=ALL;
CREATE PROFILE c##common_profile LIMIT
  PASSWORD_LIFE_TIME 90
  PASSWORD_GRACE_TIME 7
  PASSWORD_VERIFY_FUNCTION ora12c_strong_verify_function
  CONTAINER=ALL;

-- 在PDB中创建本地Profile
ALTER SESSION SET CONTAINER=pdb1;
CREATE PROFILE pdb1_admin_profile LIMIT
  PASSWORD_LIFE_TIME 30
  PASSWORD_GRACE_TIME 5
  FAILED_LOGIN_ATTEMPTS 3
  PASSWORD_LOCK_TIME UNLIMITED
  PASSWORD_VERIFY_FUNCTION ora12c_strong_verify_function;

-- 为PDB用户分配Profile
ALTER USER pdb1_admin PROFILE pdb1_admin_profile;

跨PDB密码策略同步

对于需要统一密码策略的多PDB环境,可以使用以下方法:

sql
-- 创建一个脚本来同步Profile配置
DECLARE
  CURSOR pdb_cursor IS
    SELECT NAME FROM V$PDBS WHERE OPEN_MODE = 'READ WRITE';
BEGIN
  FOR pdb IN pdb_cursor LOOP
    EXECUTE IMMEDIATE 'ALTER SESSION SET CONTAINER=' || pdb.NAME;
    
    -- 创建或修改Profile
    EXECUTE IMMEDIATE '
      CREATE OR REPLACE PROFILE app_profile LIMIT
        PASSWORD_LIFE_TIME 90
        PASSWORD_GRACE_TIME 7
        PASSWORD_REUSE_TIME 180
        PASSWORD_REUSE_MAX 10
        FAILED_LOGIN_ATTEMPTS 5
        PASSWORD_LOCK_TIME 12
        PASSWORD_MIN_LENGTH 12
        PASSWORD_VERIFY_FUNCTION ora12c_strong_verify_function
    ';
    
    DBMS_OUTPUT.PUT_LINE('已同步PDB ' || pdb.NAME || ' 的app_profile');
  END LOOP;
  
  -- 切换回CDB$ROOT
  EXECUTE IMMEDIATE 'ALTER SESSION SET CONTAINER=CDB$ROOT';
END;
/

Oracle 19c与21c密码策略差异

特性Oracle 19cOracle 21c
密码验证函数提供基本和强验证函数增强的验证函数,支持更多自定义选项
密码延迟验证支持基本延迟增强的延迟配置,可设置不同错误次数的延迟时间
临时密码支持不支持支持临时密码,首次登录必须修改
密码历史深度最大100次支持更长的密码历史记录
多租户策略PDB级Profile支持增强的PDB级策略,支持跨PDB策略继承
密码策略模板内置多种密码策略模板,快速应用
密码强度评估基础评估增强的密码强度评分和建议
集成统一审计基础集成深度集成统一审计,提供更详细的密码操作审计

生产环境最佳实践

1. 分层密码策略

根据用户类型和权限级别,实施不同强度的密码策略:

用户类型密码有效期最小长度错误尝试次数锁定时间
数据库管理员30天14位3次24小时
应用管理员60天12位5次12小时
普通应用用户90天12位5次6小时
只读用户180天10位10次3小时

2. 定期密码审计

sql
-- 审计密码策略合规性
SELECT PROFILE, RESOURCE_NAME, LIMIT
FROM DBA_PROFILES
WHERE RESOURCE_TYPE = 'PASSWORD'
  AND (
    (RESOURCE_NAME = 'PASSWORD_LIFE_TIME' AND LIMIT NOT IN ('30', '60', '90', '180')) OR
    (RESOURCE_NAME = 'PASSWORD_MIN_LENGTH' AND TO_NUMBER(LIMIT) < 10) OR
    (RESOURCE_NAME = 'FAILED_LOGIN_ATTEMPTS' AND TO_NUMBER(LIMIT) > 10) OR
    (RESOURCE_NAME = 'PASSWORD_VERIFY_FUNCTION' AND LIMIT = 'NULL')
  );

-- 审计密码即将过期的用户
SELECT USERNAME, PROFILE, EXPIRY_DATE, 
       TRUNC(EXPIRY_DATE) - SYSDATE AS DAYS_LEFT
FROM DBA_USERS
WHERE EXPIRY_DATE <= SYSDATE + 14
ORDER BY DAYS_LEFT;

3. 密码策略自动化

  • 使用Oracle Enterprise Manager或自定义脚本定期检查密码策略合规性
  • 配置密码过期提醒,提前通知用户更换密码
  • 实现自动解锁机制,对于非敏感账号可以设置自动解锁时间

4. 安全密码生成

对于批量创建用户或重置密码,应使用安全的密码生成方法:

sql
-- 生成随机密码的函数示例
CREATE OR REPLACE FUNCTION generate_secure_password(
  p_length IN NUMBER := 12
) RETURN VARCHAR2 IS
  v_password VARCHAR2(100);
  v_chars VARCHAR2(255) := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?';
BEGIN
  FOR i IN 1..p_length LOOP
    v_password := v_password || SUBSTR(v_chars, DBMS_RANDOM.VALUE(1, LENGTH(v_chars)), 1);
  END LOOP;
  RETURN v_password;
END;
/

-- 使用示例
SELECT generate_secure_password(14) AS secure_password FROM DUAL;

5. 密码策略与企业安全框架集成

  • 与企业IAM系统集成,实现统一的密码管理
  • 符合行业合规要求(如PCI DSS、HIPAA等)
  • 定期进行安全审计和渗透测试,验证密码策略有效性

常见问题(FAQ)

Q:如何查看特定用户的密码策略?

A:可以通过以下SQL查询:

sql
SELECT u.USERNAME, u.PROFILE, p.RESOURCE_NAME, p.LIMIT
FROM DBA_USERS u
JOIN DBA_PROFILES p ON u.PROFILE = p.PROFILE
WHERE u.USERNAME = 'APP_USER' AND p.RESOURCE_TYPE = 'PASSWORD';

Q:如何批量修改用户的Profile?

A:可以使用PL/SQL脚本批量修改:

sql
DECLARE
  CURSOR user_cursor IS
    SELECT USERNAME FROM DBA_USERS
    WHERE PROFILE = 'DEFAULT'  -- 原Profile
      AND USERNAME NOT IN ('SYS', 'SYSTEM', 'DBSNMP');  -- 排除系统用户
BEGIN
  FOR u IN user_cursor LOOP
    EXECUTE IMMEDIATE 'ALTER USER ' || u.USERNAME || ' PROFILE app_profile';
    DBMS_OUTPUT.PUT_LINE('已将用户 ' || u.USERNAME || ' 的Profile修改为app_profile');
  END LOOP;
END;
/

Q:密码验证函数编译失败怎么办?

A:通常是由于权限问题或函数依赖缺失导致:

sql
-- 确保用户有CREATE PROCEDURE权限
GRANT CREATE PROCEDURE TO admin_user;

-- 检查函数编译错误
SELECT * FROM USER_ERRORS WHERE NAME = 'CUSTOM_PASSWORD_VERIFY';

-- 确保函数所有者有EXECUTE权限
GRANT EXECUTE ON sys.ora12c_strong_verify_function TO admin_user;

Q:如何临时禁用密码验证?

A:可以通过设置验证函数为NULL实现:

sql
-- 临时禁用密码验证
ALTER PROFILE DEFAULT LIMIT PASSWORD_VERIFY_FUNCTION NULL;

-- 完成后重新启用
ALTER PROFILE DEFAULT LIMIT PASSWORD_VERIFY_FUNCTION ora12c_strong_verify_function;

Q:Oracle 21c的临时密码如何使用?

A:Oracle 21c支持创建带临时密码的用户,首次登录必须修改:

sql
-- 创建带临时密码的用户
CREATE USER app_user IDENTIFIED BY "TempPass_2023" TEMPORARY;

-- 用户首次登录时会被强制要求修改密码
-- SQL*Plus登录示例:
-- SQL> CONN app_user/TempPass_2023
-- Changing password for app_user
-- New password: ********
-- Retype new password: ********
-- Password changed

Q:如何配置密码过期提醒?

A:Oracle数据库本身不提供直接的邮件提醒功能,但可以通过以下方式实现:

  1. 使用Oracle Enterprise Manager的通知功能
  2. 开发自定义PL/SQL脚本,定期检查并发送邮件提醒
  3. 集成第三方监控工具,如Zabbix、Nagios等

Q:密码锁定后如何解锁?

A:可以通过ALTER USER语句解锁:

sql
-- 直接解锁
ALTER USER locked_user ACCOUNT UNLOCK;

-- 解锁并重置密码
ALTER USER locked_user IDENTIFIED BY "NewPass_2023" ACCOUNT UNLOCK;

-- 查看解锁历史(如果启用了审计)
SELECT EVENT_TIMESTAMP, DBUSERNAME, ACTION_NAME, OBJECT_NAME
FROM UNIFIED_AUDIT_TRAIL
WHERE ACTION_NAME = 'ALTER USER' 
  AND SQL_TEXT LIKE '%ACCOUNT UNLOCK%'
ORDER BY EVENT_TIMESTAMP DESC;

Q:如何防止用户使用弱密码?

A:综合使用以下措施:

  1. 启用强密码验证函数(ora12c_strong_verify_function)
  2. 设置足够长的密码最小长度(至少12位)
  3. 配置密码历史记录,防止重复使用
  4. 定期进行密码审计,识别弱密码
  5. 对管理员账号实施更严格的密码策略
  6. 教育用户使用密码管理器生成和存储强密码

总结

密码策略是Oracle数据库安全的基础组成部分,合理的密码策略配置和管理对于保障数据库安全至关重要。DBA应根据业务需求和安全要求,实施分层密码策略,定期进行密码审计和合规性检查,结合Oracle版本特性优化密码管理。

随着Oracle版本的演进,密码策略功能不断增强,特别是Oracle 21c引入的临时密码、增强的密码强度评估和多租户支持等特性,为DBA提供了更强大的密码管理能力。通过持续优化密码策略和管理流程,可以有效降低密码相关的安全风险,保障数据库系统的安全稳定运行。