Oracle 密码复杂度的设置
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Oracle 密码复杂度的设置
--某些情况下,需要强制Oracle数据库中的某些用户(例如 sys, system, 或者其他)的密码,不能太简单。
--虽然作为数据库管理人员,不会设置太简单的密码。
但是,当需要数据库级别,不允许设置太简单的密码,如果设置太简单的密码,则拒绝本次操作。
首先:先查询一下. 当前数据库中,都有哪些 profile
SELECT
DISTINCT profile
FROM
dba_profiles;
一般情况下,所有的用户,是使用一个名字叫 DEFAULT 的 profile
下面这个语句,查询 DEFAULT 的 profile ,密码方面的设置。
SQL> select
2 RESOURCE_NAME,
3 LIMIT
4 from
5 dba_profiles
6 where
7 profile='DEFAULT'
8 AND RESOURCE_TYPE = 'PASSWORD';
RESOURCE_NAME LIMIT
-------------------------------- ------------
FAILED_LOGIN_ATTEMPTS UNLIMITED
PASSWORD_LIFE_TIME UNLIMITED
PASSWORD_REUSE_TIME UNLIMITED
PASSWORD_REUSE_MAX UNLIMITED
PASSWORD_VERIFY_FUNCTION NULL
PASSWORD_LOCK_TIME UNLIMITED
PASSWORD_GRACE_TIME UNLIMITED
已选择7行。
注意到,那个 PASSWORD_VERIFY_FUNCTION 的 LIMIT 是 NULL
也就是没有任何的密码复杂度限制。
由于听说,直接执行那个 utlpwdmg.sql,会修改 DEFAULT 这个 PROFILE,从而导致影响所有的用户。
因此只好去找个那个 verify_function 的代码,手工做点修改处理。
原有的代码是数字 + 大小写 + 符号。
长度要大于等于4
现在修改为仅仅数字 + 大小写,长度要大于等于10。
--------------------------------------------------
-- 验证密码复杂度
-- 参数:
-- username 用户名
-- password 密码
-- old_password 旧密码
-- 返回值:验证是否通过.
-------------------------------------------------- CREATE OR REPLACE FUNCTION verify_function( username varchar2,
password varchar2,
old_password varchar2
) RETURN boolean IS
n boolean;
-- 用于暂存密码长度.
m integer;
differ integer;
-- 是否包含数字判断标志.
isdigit boolean;
-- 是否包含小写字母判断标志.
ischar_lower boolean;
-- 是否包含大写字母判断标志.
ischar_upper boolean;
-- 数字字符.
digitarray varchar2(20);
-- 小写字母字符.
chararray_lower varchar2(26);
-- 大写字母字符.
chararray_upper varchar2(26);
BEGIN
-- 数字字符.
digitarray:= '0123456789';
-- 小写字符.
chararray_lower:= 'abcdefghijklmnopqrstuvwxyz';
-- 大写字符
chararray_upper:='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
-- 检查是否用户名与密码是否相同
IF NLS_LOWER(password) = NLS_LOWER(username) THEN
raise_application_error(-20001, 'Password same as or similar to user'); END IF;
-- 检查密码的长度是否符合要求.
IF length(password) < 10 THEN
raise_application_error(-20002, 'Password length less than 10');
END IF;
-- 检查密码是否是简单的单词
-- (这一段理论上执行不到,因为前面加了密码长度大于 10 的限制)
IF NLS_LOWER(password) IN ('welcome', 'database', 'account', 'user', 'password', ' oracle', 'computer', 'abcd') THEN
raise_application_error(-20002, 'Password too simple');
END IF;
-- 检查密码是否至少包含一个数字、一个小写字母,一个大写字母.
-- 1. 检查数字
-- 默认密码中没有数字.
isdigit:=FALSE;
-- 取得密码长度.
m := length(password);
-- 从 0-9 循环
FOR i IN 1..10 LOOP
-- 遍历密码中的每一个字符.
FOR j IN 1..m LOOP
IF substr(password,j,1) = substr(digitarray,i,1) THEN
-- 如果存在数字字符,设置“密码中有数字”
isdigit:=TRUE;
GOTO findchar_lower;
END IF;
END LOOP;
END LOOP;
IF isdigit = FALSE THEN
raise_application_error(-20003, 'Password should contain at least one digit, one U pper character and one Lower character');
END IF;
-- 2. 检查小写字符.
<<findchar_lower>>
-- 默认密码中没有小写字符.
ischar_lower:=FALSE;
-- 从 a - z 循环.
FOR i IN 1..length(chararray_lower) LOOP
-- 遍历密码中的每一个字符.
FOR j IN 1..m LOOP
IF substr(password,j,1) = substr(chararray_lower,i,1) THEN
-- 如果存在小写字母字符,设置“密码中有小写字母”
ischar_lower:=TRUE;
GOTO findchar_upper;
END IF;
END LOOP;
END LOOP;
IF ischar_lower = FALSE THEN
raise_application_error(-20003, 'Password should contain at least one digit, one U pper character and one Lower character');
END IF;
-- 3. 检查大写字符.
<<findchar_upper>>
-- 默认密码中没有大写字符.
ischar_upper:=FALSE;
-- 从 A - Z 循环.
FOR i IN 1..length(chararray_upper) LOOP
FOR j IN 1..m LOOP
IF substr(password,j,1) = substr(chararray_upper,i,1) THEN
-- 如果存在大写字母字符,设置“密码中有大写字母”
ischar_upper:=TRUE;
-- 跳出循环,本次新密码已经包含了数字大写字母与小写字母.
GOTO endsearch;
END IF;
END LOOP;
END LOOP;
IF ischar_upper = FALSE THEN
raise_application_error(-20003, 'Password should contain at least one digit, one U pper character and one Lower character');
END IF;
<<endsearch>>
-- 检查新密码与旧密码,是否至少有3个字母的变更.
IF old_password IS NOT NULL THEN
-- 首先获取密码长度的差异.
differ := length(old_password) - length(password);
-- 如果密码长度的差异小于3,那么需要进一步判断了.
IF abs(differ) < 3 THEN
-- 设置 m = 长度比较小的那个密码的长度.
IF length(password) < length(old_password) THEN
m := length(password);
ELSE
m := length(old_password);
END IF;
differ := abs(differ);
-- 新旧密码字符比较.
FOR i IN 1..m LOOP
IF substr(password,i,1) != substr(old_password,i,1) THEN
differ := differ + 1;
END IF;
END LOOP;
IF differ < 3 THEN
raise_application_error(-20004, 'Password should differ by at least 3 characters'); END IF;
END IF;
END IF;
-- Everything is fine; return TRUE ;
RETURN(TRUE);
END;
/
上面的存储过程,需要用 conn / as sysdba 登录到 Oracle 后进行创建.
否则后面创建 PROFILE 的时候,会出错。
存储过程创建完毕以后,创建一个 PROFILE
CREATE PROFILE my_profile LIMIT
PASSWORD_VERIFY_FUNCTION VERIFY_FUNCTION;
因为我其他全部使用默认值,仅仅修改一个 PASSWORD_VERIFY_FUNCTION 因此这里创建的时候,就仅仅指定一行.
然后修改一个测试用户的 PROFILE
ALTER USER test_user PROFILE my_profile;
然后尝试修改这个测试用户的密码
alter user test_user identified by "123";
SQL> alter user test_user identified by "123";
alter user test_user identified by "123"
*
第 1 行出现错误:
ORA-28003: 指定口令的口令验证失败
ORA-20002: Password length less than 10
SQL> alter user test_user identified by "1234567890";
alter user test_user identified by "1234567890"
*
第 1 行出现错误:
ORA-28003: 指定口令的口令验证失败
ORA-20003: Password should contain at least one digit, one Upper character and one Lower character
SQL> alter user test_user identified by "1234567890A";
alter user test_user identified by "1234567890A"
*
第 1 行出现错误:
ORA-28003: 指定口令的口令验证失败
ORA-20003: Password should contain at least one digit, one Upper character and one Lower character
SQL> alter user test_user identified by "1234567890Aa";
用户已更改。