外观
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_11g | Oracle 11g | 8位+大小写字母+数字+特殊字符 | 11g升级环境 |
| ora12c_verify_function | Oracle 12c+ | 8位+大小写字母+数字 | 测试环境 |
| ora12c_strong_verify_function | Oracle 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 19c | Oracle 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 changedQ:如何配置密码过期提醒?
A:Oracle数据库本身不提供直接的邮件提醒功能,但可以通过以下方式实现:
- 使用Oracle Enterprise Manager的通知功能
- 开发自定义PL/SQL脚本,定期检查并发送邮件提醒
- 集成第三方监控工具,如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:综合使用以下措施:
- 启用强密码验证函数(ora12c_strong_verify_function)
- 设置足够长的密码最小长度(至少12位)
- 配置密码历史记录,防止重复使用
- 定期进行密码审计,识别弱密码
- 对管理员账号实施更严格的密码策略
- 教育用户使用密码管理器生成和存储强密码
总结
密码策略是Oracle数据库安全的基础组成部分,合理的密码策略配置和管理对于保障数据库安全至关重要。DBA应根据业务需求和安全要求,实施分层密码策略,定期进行密码审计和合规性检查,结合Oracle版本特性优化密码管理。
随着Oracle版本的演进,密码策略功能不断增强,特别是Oracle 21c引入的临时密码、增强的密码强度评估和多租户支持等特性,为DBA提供了更强大的密码管理能力。通过持续优化密码策略和管理流程,可以有效降低密码相关的安全风险,保障数据库系统的安全稳定运行。
