Oracle如何限制非法呼叫包中過程

indexman發表於2015-06-28

原文:http://www.oracle.com/technetwork/issue-archive/2015/15-jan/o15plsql-2398996.html
假如我有一個包P_A,其中封裝了重要過程DO_A。
另有一個包P_B需要呼叫P_A.DO_A實現重要商業邏輯。
我想只授權給包P_B呼叫,認為其他途徑呼叫P_A.DO_A都是非法的!
下面根據PL/SQL開發大師[福伊爾斯坦]提供的方法實現如下:

CREATE OR REPLACE PACKAGE p_a IS
PROCEDURE do_a;
END p_a;
/

CREATE OR REPLACE PACKAGE BODY p_a IS
PROCEDURE do_a IS
BEGIN
dbms_output.put_line(‘DO_A FROM P_A’);
END do_a;
END p_a;
/

CREATE OR REPLACE PACKAGE P_B
IS
PROCEDURE DO_B;
END P_B;
/

CREATE OR REPLACE PACKAGE BODY P_B
IS
PROCEDURE DO_B
IS
BEGIN
P_A.DO_A;
END DO_B;
END P_B;
/

BEGIN
P_A.DO_A; –被認為是非法呼叫
P_B.DO_B; –唯一合法呼叫
END;
/

–如何限制只有P_B可呼叫P_A.DO_A?
–12c以前,我們使用DBMS_UTILITY .FORMAT_CALL_STACK
–編寫自定義函式:
CREATE OR REPLACE FUNCTION i_was_called_by (program_in IN VARCHAR2)
RETURN BOOLEAN
IS
c_stack CONSTANT VARCHAR2 (32767)
:= DBMS_UTILITY.format_call_stack;
BEGIN
RETURN INSTR (SUBSTR (c_stack,
INSTR (c_stack,
CHR (10),1,5)+ 1,
INSTR (c_stack, CHR (10),1,6)
- INSTR (c_stack,CHR (10),1,5)
+ 1),
program_in) > 0;
END;

—– PL/SQL Call Stack —–
object line object
handle number name
000007FF50456200 4 function SCOTT.I_WAS_CALLED_BY
000007FF504ADD28 4 package body SCOTT.P_A
000007FF50439820 2 anonymous block

–修改P_A.DO_A過程:
PROCEDURE DO_A
IS
BEGIN
IF i_was_called_by (‘P_B’)
THEN
dbms_output.put_line(‘DO_A FROM P_A’);
ELSE
RAISE_APPLICATION_ERROR(-20209, ‘非法呼叫!’);
END IF;
END;
/

–再次呼叫發現
BEGIN
*
第 1 行出現錯誤:
ORA-20209: 非法呼叫!
ORA-06512: 在 “SCOTT.P_A”, line 7
ORA-06512: 在 line 2

–12c以後,我們使用包的ACCESSIBLE BY條件
–修改包P_A說明部分
CREATE OR REPLACE PACKAGE p_a
ACCESSIBLE BY(P_B)
IS
PROCEDURE do_a;
END p_a;
/

相關文章