Oracle 密码复杂度的设置.docx
《Oracle 密码复杂度的设置.docx》由会员分享,可在线阅读,更多相关《Oracle 密码复杂度的设置.docx(8页珍藏版)》请在冰豆网上搜索。
![Oracle 密码复杂度的设置.docx](https://file1.bdocx.com/fileroot1/2022-12/14/15cfbdbb-ea55-44ad-99cb-1f8e8069df5f/15cfbdbb-ea55-44ad-99cb-1f8e8069df5f1.gif)
Oracle密码复杂度的设置
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 Upper character and one Lower character');
END IF;
-- 2. 检查小写字符.
<>
-- 默认 密码中没有小写字符.
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 Upper character and one Lower character');
END IF;
-- 3. 检查大写字符.
<>
-- 默认 密码中没有大写字符.
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 Upper character and one Lower character');
END IF;
<>
-- 检查新密码与旧密码, 是否至少有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";
用户已更改。