方法2:9i在win2000下使用wrap加密存储过程,10g可以用加密包dbms_ddl.wrap或dbms_ddl.create_wrapped。
11.5.1在win2000下使用wrap加密存储过程
wrap.bat
rem使用方法:wrap待加密的文件名
setNLS_LANG=AMERICAN_AMERICA.USACII7
wrap.exeiname=%1
pause
11.5.2WRAP程序包(10.2版本)
PL/SQL程序单元经常包含关于公司流程和商业秘密的非常敏感和机密的信息,这使得它们与表相类似,成为受保护的实体组。为防止未经授权而查看源代码的情况,我们要经常使用wrap命令行实用程序,这将使程序变得很混乱。
只有在创建PL/SQL脚本后才能调用wrap;该实用程序将输入的明文打包为一个文件。但是,在某些情况下,您可能希望在PL/SQL代码中动态生成包装。在这种情况下,因为还不存在源文件,不能调用wrap实用程序。
由于Oracle数据库10g第2版提供了一个供应程序包,您可以使用它创建代码,并进行打包。该程序包补充(而不是替代)了wrap实用程序。而后者仍然适合于希望使用命令行来快速打包大量源文件的情况。
例如,假设您希望以打包形式创建简单的过程p1。
createorreplaceprocedurep1as
begin
null;
end;
在PL/SQL单元中,您可以使用以下命令以打包方式动态地创建这一过程:
begin
dbms_ddl.create_wrapped
('createorreplaceprocedurep1asbeginnull;end;')
end;
/
现在您希望确认打包过程。您可以从字典中选择源文本。
SQL>selecttextfromuser_sourcewherename='P1';
Text
-----------------------------------------------------------------
procedurep1wrapped
a000000
369
abcd
abcd
……等等……
第一行procedurep1wrapped是确认以打包方式创建过程。如果您利用DBMS_METADATA.GET_DDL()函数来获取该过程的DDL,则仍然会看到源代码已被打包。
有时您可能会有略微不同的需求;例如,您可能要生成PL/SQL代码,但不想创建过程。在这种情况下,您可以将其保存在一个文件或表中,以便以后执行。但是因为以上方法创建了过程,所以该方法在这里行不通。所以您需要在程序包中调用另一个函数:
SQL>selectdbms_ddl.wrap
2('createorreplaceprocedurep1asbeginnull;end;')
3fromdual
4/
DBMS_DDL.WRAP('CREATEORREPLACEPROCEDUREP1ASBEGINNULL;END;')
----------------------------------------------------------------------
createorreplaceprocedurep1wrapped
a000000
369
abcd
abcd
...andsoon...
WRAP函数的输出是一个可传递的参数,它代表着PL/SQL代码的打包输出结果。该参数可以保存在纯文件文件或表中,可以在以后执行。如果您生成的代码要在其他地方部署,并且必须要保证代码的安全性,则这种方法很有用。
如果您可以将所存储代码的全部文本作为一个varchar2数据类型(大小限制为32K)来传递,则这一方法可以正常工作。如果PL/SQL代码超过32K,则您必须使用一种略微不同的方法:接受一个集合变量作为输入。
在这里您可以使用一个供应的数据类型:程序包DBMS_SQL中的varchar2。这是一个集合数据类型(TABLEOFVARCHAR2),表的每个单元都接收多达32K的文本;可随意增加该表所含的单元数,以满足您的需要。例如,假设您必须包装一个名为myproc的非常长的过程,其定义如下:
createorreplaceproceduremyprocas
l_keyVARCHAR2(200);
begin
l_key:='ARUPNANDA';
end;
当然,这根本不是一个非常长的过程;但是为了示范起见,假设它很长。为了将其创建为打包形式,您要执行以下的PL/SQL块:
1declare
2l_input_codedbms_sql.varchar2s;
3begin
4l_input_code(1):='ArraytoholdtheMYPROC';
5l_input_code(2):='createorreplaceproceduremyprocas';
6l_input_code(3):='l_keyVARCHAR2(200);';
7l_input_code(4):='begin';
8l_input_code(5):='l_key:=''ARUPNANDA'';';
9l_input_code(6):='end;';
10l_input_code(7):='theend';
11sys.dbms_ddl.create_wrapped(
12ddl=>l_input_code,
13lb=>2,
14ub=>6
15);
16*end;
在这里我们定义了一个变量l_input_code来保存输入的明文代码。在第4行到第10行中,我们用要打包的代码来填充这些行。在本示例中,同样为了简单起见,我使用了非常短的行。实际上,您可能要使用非常长的行,其大小多达32KB。同样,我在数组中只使用了7个单元;实际上您可能要使用若干单元来填充全部代码。
第11到第15行表明我如何调用该过程,以便将该过程创建为打包形式。在第12行中,我将集合作为一个参数DDL来传递。但是,在这里暂停一下—我已经分配了一个注释作为数组的第一个单元,可能用于文档。但它不是有效的语法。同样,我将另一个注释分配给数组的最后一个单元(7),它也不是用于创建过程的有效语法。为了使包装操作仅仅处理有效的行,我在第13和第14行中指定了存储我们代码的集合的最低(2)和最高(6)的单元。参数LB表示数组的下界,在本示例中是2,而HB是上界(6)。
使用这种方法,现在可以从您的PL/SQL代码中以打包方式创建任意大小的过程。
============================================================
CREATEORREPLACEPROCEDUREp_wraped_userAUTHIDCURRENT_USERAS
--Createdbyxsbon2006-11-10
--For:批量加密本用户下的所有代码,包括存储过程、函数、包。
v_procsdbms_sql.varchar2a;
BEGIN
FORnIN(SELECTDISTINCTNAME,TYPE
FROMuser_source
WHERENAME<>'P_WRAPED_USER'AND
TYPE<>'TYPE'
MINUS
SELECTDISTINCTNAME,TYPE
FROMuser_source
WHEREline=1AND
instr(text,'wrapped')>0
--WHERENAME='GET_CLERK'--AND
--TYPE='PACKAGEBODY'
ORDERBYTYPE)LOOP
FORiIN(SELECTrownumrn,text
FROM(SELECTdecode(line,1,'createorreplace')||texttext
FROMuser_source
WHERENAME=n.NAMEAND
TYPE=n.TYPE
ORDERBYline))LOOP
v_procs(i.rn):=i.text;
ENDLOOP;
dbms_ddl.create_wrapped(v_procs,1,v_procs.COUNT);
v_procs.DELETE;
ENDLOOP;
END;