CREATE PROFILE

为保障数据库的安全性,您可能需要对用户密码的生命周期和复杂度进行统一管理,例如强制用户定期更换密码、设置密码重试次数限制以防止暴力破解,或定义密码必须包含数字和特殊字符。PolarDB PostgreSQL版(兼容Oracle)提供的PROFILE(配置文件)功能正是为了满足这些需求。通过创建和应用PROFILE,您可以集中定义和实施一套完整的密码安全策略,从而提升整个数据库系统的安全水位。

功能简介

PROFILEPolarDB PostgreSQL版(兼容Oracle)中的一个数据库对象,它包含了一组用于管理用户密码策略的参数。您可以创建一个或多个PROFILE,并将它们分配给不同的数据库用户。

每个用户都需关联一个PROFILE。如果在创建用户时未明确指定,系统会自动为其分配名为DEFAULT的默认配置文件。通过CREATE PROFILE命令,您可以自定义密码策略,并通过ALTER PROFILEALTER USER命令进行管理和分配。

前提条件

您的PolarDB PostgreSQL版(兼容Oracle)集群的修订版本需为2.0.14.17.36.0及以上

说明

您可在控制台查看内核小版本号,也可以通过SHOW polardb_version;语句查看。如未满足内核小版本要求,请升级内核小版本

优势

  • 集中化管理:将密码策略从应用程序或手动管理中解放出来,由数据库统一强制执行,确保了策略的一致性和可靠性。

  • 提升安全性:通过密码有效期、重试锁定、复杂度校验等多种机制,有效抵御暴力破解、弱密码等常见的安全威胁。

  • 高度灵活:支持创建多个不同的PROFILE,可以为不同安全等级的用户(如管理员、普通用户、应用账户)应用不同的密码策略。

注意事项

PROFILE对象的作用域仅限于其被创建的数据库。创建、修改、查询和分配PROFILE都需在同一个数据库中进行。

语法说明

CREATE PROFILE profile_name LIMIT
    { password_parameter { integer | UNLIMITED | DEFAULT } } [, ...]

参数说明
PROFILE主要包含以下密码策略相关的参数:

参数名称

默认值

取值范围

描述

FAILED_LOGIN_ATTEMPTS

UNLIMITED

1-UNLIMITED

连续登录失败的次数上限。达到此上限后,账户将被锁定。

PASSWORD_LIFE_TIME

UNLIMITED

1-UNLIMITED

密码的有效期,单位为天。超过此期限后,用户在下次登录时必须更改密码。

PASSWORD_REUSE_TIME

UNLIMITED

1-UNLIMITED

密码重用间隔时间,单位为天。在此天数内,用户不能重复使用旧密码。

PASSWORD_REUSE_MAX

UNLIMITED

1-UNLIMITED

密码重用次数限制。在可以重用一个旧密码之前,用户必须更改密码的次数。

PASSWORD_VERIFY_FUNCTION

NULL

函数名或NULL

用于验证密码复杂度的自定义PL/SQL函数名。

PASSWORD_LOCK_TIME

UNLIMITED

1-UNLIMITED

账户因登录失败而被锁定的持续时间,单位为天。

PASSWORD_GRACE_TIME

UNLIMITED

1-UNLIMITED

密码过期后的宽限期,单位为天。在此期间,用户登录时会收到警告但仍可登录。

每个参数可以设置为一个具体的整数值、UNLIMITED(无限制)或DEFAULT(使用默认配置文件的设置)。PASSWORD_VERIFY_FUNCTION还可以设置为NULL,表示不进行复杂度验证。

使用示例

以下示例将引导您完成PROFILE的创建、分配和管理全过程。

1.(可选)创建密码复杂度验证函数

要强制密码的复杂度,您需要先创建一个密码验证函数。该函数在用户设置或修改密码时被调用,如果密码不符合规则,函数应抛出异常来阻止操作。

-- 创建一个名为pwd_verify的函数
CREATE OR REPLACE FUNCTION public.pwd_verify(
  username     IN VARCHAR2,
  password     IN VARCHAR2,
  old_password IN VARCHAR2
) RETURN BOOLEAN
AS
BEGIN
  -- 规则1:密码不能为空
  IF password IS NULL THEN
    RAISE_APPLICATION_ERROR(-20000, '密码不能为空');
  END IF;

  -- 规则2:密码长度至少为8位
  IF LENGTH(password) < 8 THEN
    RAISE_APPLICATION_ERROR(-20001, '密码长度至少为8位');
  END IF;

  -- 规则3:密码必须包含至少1个大写字母、1个小写字母和1个特殊字符
  IF NOT REGEXP_LIKE(password, '[A-Z]') OR 
     NOT REGEXP_LIKE(password, '[a-z]') OR
     NOT REGEXP_LIKE(password, '[^A-Za-z0-9]') THEN
    RAISE_APPLICATION_ERROR(-20002, '密码必须包含大写字母、小写字母和特殊字符');
  END IF;

  RETURN TRUE;
END;
/

您也可以根据自己的安全要求,在函数中实现更复杂的验证逻辑,例如检查密码是否包含用户名、是否与历史密码过于相似等。

自定义密码验证函数示例

-- 创建自定义密码验证函数示例
CREATE OR REPLACE FUNCTION custom_password_verify
(username VARCHAR2, password VARCHAR2, old_password VARCHAR2)
RETURN BOOLEAN IS
BEGIN
    -- 检查密码长度
    IF LENGTH(password) < 8 THEN
        RAISE_APPLICATION_ERROR(-20001, '密码长度至少8位');
    END IF;

    -- 检查是否包含数字
    IF NOT REGEXP_LIKE(password, '[0-9]') 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, '[a-z]') THEN
        RAISE_APPLICATION_ERROR(-20004, '密码必须包含小写字母');
    END IF;

    -- 检查是否包含特殊字符
    IF NOT REGEXP_LIKE(password, '[^A-Za-z0-9]') THEN
        RAISE_APPLICATION_ERROR(-20005, '密码必须包含特殊字符');
    END IF;

    RETURN TRUE;
END;

2. 创建PROFILE

使用CREATE PROFILE命令创建一个新的配置文件,并指定各项安全策略。

-- 创建一个名为secure_profile的配置文件
CREATE PROFILE secure_profile LIMIT
    FAILED_LOGIN_ATTEMPTS 3         -- 最多允许3次登录失败
    PASSWORD_LIFE_TIME 60           -- 密码有效期60天
    PASSWORD_REUSE_TIME 30          -- 30天内不能重用旧密码
    PASSWORD_REUSE_MAX 5            -- 必须更换5次密码后才能重用
    PASSWORD_VERIFY_FUNCTION pwd_verify -- 使用上一步创建的函数验证复杂度
    PASSWORD_LOCK_TIME 1            -- 账户锁定1天
    PASSWORD_GRACE_TIME 7;          -- 密码过期后有7天宽限期

3. 查看PROFILE信息

您可以通过查询dba_profiles视图来确认PROFILE的配置信息。

-- 查看 PROFILE 信息
SELECT *
FROM dba_profiles
WHERE profile = 'SECURE_PROFILE'
ORDER BY profile, resource_name;

4. 将PROFILE分配给用户

PROFILE创建后,需要将其分配给用户才能生效。

  • 创建新用户时分配:

    CREATE USER john_doe IDENTIFIED BY "SecurePass123!" PROFILE secure_profile;
  • 为现有用户分配:

    ALTER USER jane_doe PROFILE secure_profile;

5. 管理用户账户状态

当用户的账户因触发PROFILE中的策略(如登录失败次数过多)而被锁定时,您需要手动进行解锁。

  • 解锁用户账户:

    ALTER USER john_doe ACCOUNT UNLOCK;
  • 重置密码并解锁:
    在重置用户密码的同时,账户也会自动被解锁。

    ALTER USER john_doe IDENTIFIED BY "NewSecurePass456!" ACCOUNT UNLOCK;

常见问题

用户设置密码时提示不符合复杂度要求,如何解决?

这通常是因为新密码未能通过PROFILE中指定的PASSWORD_VERIFY_FUNCTION函数的验证。请检查该函数的具体逻辑,并确保新密码满足所有规则(如长度、字符类型等)。

用户账户经常被锁定?

这可能是由以下原因造成的:

  1. FAILED_LOGIN_ATTEMPTS设置过低:用户可能因为正常的输错密码而被锁定。您可以考虑使用ALTER PROFILE适当调高此值。

  2. 恶意攻击或程序错误:检查数据库日志,确认是否有来自未知IP的暴力破解尝试,或是否有自动化脚本使用了错误的密码凭据在持续尝试连接。

  3. 锁定时间过长:如果PASSWORD_LOCK_TIME设置得过长,会导致用户等待时间过久。可以适当调整此值,或在确认安全后手动为用户解锁。