您的位置:首页 > 数据库

介绍一个产生随机密码的PL/SQL函数

2015-12-16 09:53 246 查看
产生随机密码的基础是产生随机数。

首先,必须有种子。

DBMS_RANDOM.seed(l_seed)

这个种子可以是字符串。为了增加随机性,这个种子字符串可以从Timestamp来获取。

比如,l_seed := to_char(SYSTIMESTAMP,'YYYYDDMMHH24MISSFFFF');

其次,有Value函数。

DBMS_RANDOM.value(mix,max);

给出最小和最大值就可以产生指定范围的随机数。

步骤:

1. 按照函数自变量指定的各类字符(L,小写字母;U-大写字母;D-数字;S-其他符号)的长度,缺省值大家都是1,

产生一个包含LUDS的字符串,其长度是所要产生的密码的长度。

比如,要产生的密码长度为8,可以得到LUDSLUDS。

2. 然后把这个字符串洗牌,得到随机的字符串,比如SLDUDLUS。

3. 最后,按以上随机顺序,分别从各种字符的全集中随机取得各个字符,按照步骤2得到的顺序,拼凑一个密码。

比如 %b9H2aK$。

请看代码:

create or replace function key_gen(
p_len number default 12,
p_use_lcs number default 1,
p_use_ucs number default 1,
p_use_dgt number default 1,
p_use_smb number default 1,
p_use_hex char default 'N',
p_esy_rec char default 'N',
p_smb_str varchar2 default null
)
return varchar2 is

l_use_ptn varchar2(1000);
l_use_ptn_len number;
l_use_str varchar2(4000);
l_use_typ varchar2(10);

l_seed varchar2(100);
l_lcs varchar2(26):= 'abcdefghijklmnopqrstuvwxyz';
l_lcs_len number;
l_ucs varchar2(26):= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
l_ucs_len number;
l_dgt varchar2(10):= '0123456789';
l_dgt_len number;
l_smb varchar(50) := q'#!"#$%&'()=~`{+*}<>?_-^\@[;:],./\'#';
l_smb_len number;
l_hex varchar2(16):= '0123456789abcdef';
l_hex_len number;
l_key varchar2(4000);

l_p1 number;

begin

if Upper(p_esy_rec) = 'Y' then
l_lcs := 'abcdefghijkmnpqrstuvwxyz';
l_ucs := 'ABCDEFGHIJKLMNPQRSTUVWXYZ';
l_dgt := '23456789';
l_smb := q'|!#$%&=+*?-@|';
end if;

if p_smb_str is not null then
l_smb :=  p_smb_str;
end if;

l_lcs_len := lengthb(l_lcs);
l_ucs_len := lengthb(l_ucs);
l_dgt_len := lengthb(l_dgt);
l_smb_len := lengthb(l_smb);
l_hex_len := lengthb(l_hex);

l_use_ptn := Null;
l_use_ptn := l_use_ptn || Trim(rpad(' ',p_use_lcs+1,'L')); -- Put number of Lowercase into pattern
l_use_ptn := l_use_ptn || Trim(rpad(' ',p_use_ucs+1,'U')); -- Put number of Uppercase into pattern
l_use_ptn := l_use_ptn || Trim(rpad(' ',p_use_dgt+1,'D')); -- Put number of Digit into pattern
l_use_ptn := l_use_ptn || Trim(rpad(' ',p_use_smb+1,'S')); -- Put number of Symbol into pattern

if Upper(p_use_HEX) = 'Y' then -- If hex, excludes others
l_use_ptn := Trim(rpad(' ',p_len+1,'H'));
end if;

l_use_str := l_use_ptn; -- Compose character type sequence, LUCDSLUCDS....
if replace(l_use_ptn,'S','') is not null then
l_use_ptn := replace(l_use_ptn,'S',''); -- Replace S(=symble) if any. Since we need only specified numbers of symble
end if;

loop
l_use_str := l_use_str||l_use_ptn;
exit when lengthb(l_use_str)>=p_len;
end loop;
l_use_str := Substr(l_use_str,1,p_len);
--htp.p(l_use_str);

l_seed := to_char(SYSTIMESTAMP,'YYYYDDMMHH24MISSFFFF');
DBMS_RANDOM.seed(l_seed);

-- Randomize the LUDSLUDS sequence
for i in 1 .. p_len loop
l_p1 := ROUND(DBMS_RANDOM.value(1,p_len));
l_use_str := substr(l_use_str,1,l_p1-1)||substr(l_use_str,l_p1+1)||Substr(l_use_str,l_p1,1);
end loop;

l_key := NULL;
for i in 1 .. p_len loop
l_use_typ := substr(l_use_str,i,1);

case l_use_typ
when 'L' then
l_p1 := ROUND(DBMS_RANDOM.value(1,l_lcs_len));
l_key := l_key||substr(l_lcs,l_p1,1);
when 'U' then
l_p1 := ROUND(DBMS_RANDOM.value(1,l_ucs_len));
l_key := l_key||substr(l_ucs,l_p1,1);
when 'D' then
l_p1 := ROUND(DBMS_RANDOM.value(1,l_dgt_len));
l_key := l_key||substr(l_dgt,l_p1,1);
when 'S' then
l_p1 := ROUND(DBMS_RANDOM.value(1,l_smb_len));
l_key := l_key||substr(l_smb,l_p1,1);
when 'H' then
l_p1 := ROUND(DBMS_RANDOM.value(1,l_hex_len));
l_key := l_key||substr(l_hex,l_p1,1);
end case;

end loop;

return l_key;
end;​


说明:

自变量有以下8个,每个都有各自的缺省值。如果不指定任何自变量而执行函数,就可以按照缺省值得到一个随机密码。

这可以满足大多数人的要求。

1. 密码长度,缺省值=12。 p_len number default 12,

2. 使用小写字母的最小个数,缺省值=1。0为不使用 p_use_lcs number default 1,

3. 使用大写字母的最小个数,缺省值=1。0为不使用 p_use_ucs number default 1,

4. 使用数字的最小个数,缺省值=1。0为不使用 p_use_dgt number default 1,

5. 使用符号的最小个数,缺省值=1。0为不使用 p_use_smb number default 1,

6. 是否使用16进数产生密码,缺省值=N(不使用) p_use_hex char default 'N',

此变量优先度高。如果指定为Y或y,第2-5项变量自动为0.

7. 是否产生易读的密码,缺省值=N(不使用) p_esy_rec char default 'N',

如果指定为Y或y,则不使用容易混淆的字母/数字/符号。比如0/O,1/l,以及一些不易记忆的符号。

8. 用户指定的符号字符串,缺省为Null。 p_smb_str varchar2 default null

此变量优先度高。如果指定,将取代函数中预设的符号字符串。这可以使得用户使用自己可以接受的符号,

比如只使用“#$%&”这4个符号。

使用例子:

1. 完全使用缺省值。产生一个12字符的密码。

select KEY_GEN() FROM DUAL;

KEY_GEN()

v2M02pH/EouB

2. 指定长度,产生一个8字符的密码。

select KEY_GEN(8) FROM DUAL;

KEY_GEN(8)

tNiC%5s1

3.产生一个由16进数组成的密码。长度为12(缺省)。

select KEY_GEN(p_use_hex=>'Y') FROM DUAL;

KEY_GEN(P_USE_HEX=>'Y')

2684dd8cf3ad

4.产生一个包含2个符号的密码,但是符号只包含“#$%&”长度为12(缺省)。

select KEY_GEN(p_smb_str=>'#$%&', p_use_smb=>2) password FROM DUAL;

PASSWORD

lpW1Ux1$S7v%
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: