溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Oracle中定義者權限和調(diào)用者權限的示例分析

發(fā)布時間:2021-12-13 15:18:38 來源:億速云 閱讀:147 作者:小新 欄目:關系型數(shù)據(jù)庫

這篇文章給大家分享的是有關Oracle中定義者權限和調(diào)用者權限的示例分析的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

定義者權限:定義者權限指使用它所有者的權限,而不是當前用戶來執(zhí)行過程。因此,你可以限制用戶執(zhí)行的數(shù)據(jù)庫操作,允許他們僅通過運行定義者權限的過程和函數(shù)訪問數(shù)據(jù)。創(chuàng)建過程、函數(shù)和程序包的默認權限是定義者權限。

 

調(diào)用者權限:在當前的用戶模式下用當前的用戶權限來執(zhí)行過程。換句話說,就是調(diào)用者的權限過程并不與某個特定的用戶或模式綁定。調(diào)用者權限程序可以使應用程序開發(fā)人員很容易的將應用邏輯集中起來,即使底層的數(shù)據(jù)在用戶和模式中被劃分。創(chuàng)建時需要顯式使用AUTHID CURRENT_USER來定義調(diào)用者過程。

(注意:在閱讀下面案例的時候注意sqlplus的使用的不同用戶)

具體演示如下所示:

1、創(chuàng)建兩個測試用戶wjq1和wjq2,并分別授權

SYS@seiang11g>create user wjq1 identified by wjq1 default tablespace seiang;

User created.

SYS@seiang11g>create user wjq2 identified by wjq2 default tablespace seiang;

User created.

SYS@seiang11g>grant connect,resource to wjq1,wjq2;

Grant succeeded.

2、切換到用戶wjq1,創(chuàng)建兩個過程proc_definer和proc_invoker

過程1:定義者權限,為創(chuàng)建過程的默認權限

WJQ1@seiang11g>create or replace procedure proc_definer is

  2  begin

  3     dbms_output.put_line('Current User:'|| sys_context('userenv','current_user'));

  4     dbms_output.put_line('Session User:'|| sys_context('userenv','session_user'));

  5     dbms_output.put_line('Current Schema:'|| sys_context('userenv','current_schema'));

  6  end proc_definer;

  7  /

Procedure created.

過程2:使用使用者權限

WJQ1@seiang11g>create or replace procedure proc_invoker authid current_user is

  2  begin

  3     dbms_output.put_line('Current User:'|| sys_context('userenv','current_user'));

  4     dbms_output.put_line('Session User:'|| sys_context('userenv','session_user'));

  5     dbms_output.put_line('Current Schema:'|| sys_context('userenv','current_schema'));

  6  end proc_invoker;

  7  /

Procedure created.

3、查看兩個過程的權限

WJQ1@seiang11g>select object_name,procedure_name,authid from user_procedures

  2  where object_name like '%PROC%';

OBJECT_NAME                    PROCEDURE_NAME                 AUTHID

------------------------------ ------------------------------ ------------

PROC_INVOKER                                                  CURRENT_USER

PROC_DEFINER                                                  DEFINER

4、在用戶wjq1下分別執(zhí)行定義者權限和使用者權限的過程

WJQ1@seiang11g>set serveroutput on

WJQ1@seiang11g>

WJQ1@seiang11g>exec proc_definer;

Current User:WJQ1

Session User:WJQ1

Current Schema:WJQ1

PL/SQL procedure successfully completed.

WJQ1@seiang11g>exec proc_invoker;

Current User:WJQ1

Session User:WJQ1

Current Schema:WJQ1

PL/SQL procedure successfully completed.

5、將用戶wjq1創(chuàng)建的兩個過程授權給用戶wjq2

WJQ1@seiang11g>grant execute on proc_definer to wjq2;

Grant succeeded.

WJQ1@seiang11g>grant execute on proc_invoker to wjq2;

Grant succeeded.

6、在用戶wjq2下分別調(diào)用兩個過程,結果顯示在調(diào)用者權限下,程序在當前用戶下用當前用戶的權限執(zhí)行

WJQ2@seiang11g>set serveroutput on

WJQ2@seiang11g>exec wjq1.proc_definer;

Current User:WJQ1

Session User:WJQ2

Current Schema:WJQ1

PL/SQL procedure successfully completed.

WJQ2@seiang11g>exec wjq1.proc_invoker;

Current User:WJQ2

Session User:WJQ2

Current Schema:WJQ2

PL/SQL procedure successfully completed.

通過上面的簡單的演示,已經(jīng)對定義者權限和調(diào)用者權限有了一定的認識和理解,但是僅僅初步的了解在生產(chǎn)環(huán)境中,遇到實際的案例還是有點摸不著頭腦,下面通過兩個實際的案例來分析定義者權限和調(diào)用者權限,更加深入的去理解它們的使用方法。

在存儲過程中,時常會遇到這樣一種場景:用戶A下有一個存儲過程(或者函數(shù)體、包體)Proc,在過程中間引用了對象obj。在編譯存儲過程時,是要求用戶A有對象obj的權限的,如果沒有,則系統(tǒng)報編譯錯誤。當成功進行編譯之后,用戶A將執(zhí)行execute存儲過程Proc的權限賦給了用戶B。但是用戶B不一定擁有對象obj的使用權限,那么問題就來了,此時用戶B能否成功執(zhí)行存儲過程Proc呢?

下面我們通過實驗來進行驗證:

接著上面例子,用戶wjq1和wjq2除了擁有connect和resource角色的權限之外,出于實驗的目的,我們將select any dictionary的系統(tǒng)權限賦予給用戶wjq1

SYS@seiang11g>grant select any dictionary to wjq1;

Grant succeeded.

select any dictionary的系統(tǒng)權限意味著用戶可以訪問數(shù)據(jù)字典視圖層面的視圖中的對象數(shù)據(jù)。

WJQ1@seiang11g>select count(*) from dba_objects;

  COUNT(*)

----------

     86993

WJQ1@seiang11g>create or replace procedure proc_wjq1 is

  2  i number;

  3  begin

  4     select count(*) into i from dba_objects;

  5     dbms_output.put_line(to_char(i));

  6  end;

  7  /

Procedure created.

WJQ1@seiang11g>set serveroutput on

WJQ1@seiang11g>

WJQ1@seiang11g>exec proc_wjq1;

86994

PL/SQL procedure successfully completed. 

由上可見:授予select any dictionary的用戶wjq1可以對dba_objects視圖進行訪問操作。同時,存儲過程proc_wjq1也可以執(zhí)行編譯操作。

案例一:定義者權限

緊接著上面的實驗,對于wjq2用戶,只有執(zhí)行wjq1用戶下proc_wjq1存儲過程權限,但是沒有訪問dba_objects視圖權限,看實際效果。

用戶wjq2只具有基本的connect和resource權限。將proc_wjq1過程的執(zhí)行權限授權給wjq2

WJQ1@seiang11g>grant execute on proc_wjq1 to wjq2;

Grant succeeded. 

之后,檢查wjq2用戶下,過程proc_wjq1的執(zhí)行情況

WJQ2@seiang11g>select count(*) from dba_objects;

select count(*) from dba_objects

                     *

ERROR at line 1:

ORA-00942: table or view does not exist

wjq2用戶沒有dba_objects權限,顯示訪問必然報錯

WJQ2@seiang11g>exec wjq1.proc_wjq1;

86994

PL/SQL procedure successfully completed.

結果顯而易見,wjq2雖然沒有訪問dba_objects權限,但是因為擁有執(zhí)行proc_wjq1的權限,在執(zhí)行proc_wjq1的時候,也是可以在方法中訪問到dba_objects。顯然,此時wjq2在執(zhí)行proc_wjq1上應用了wjq1用戶對于dba_objects的權限,也就是對象定義者的權限。

為了進一步證明結果的準確性,下面將繼續(xù)進行實驗變化來演示

當定義者權限失去時,即使調(diào)用者擁有權限也是無用的(也就是說wjq1用戶沒有訪問dba_objects的權限,wjq2用戶有訪問dba_objects的權限)

回收了wjq1用戶上的select any dictionary權限,此時wjq1對dba_objects對象權限消失;然后,賦予wjq2用戶select any dictionary權限,這樣wjq2就能訪問dba_objects了

SYS@seiang11g>revoke select any dictionary from wjq1;

Revoke succeeded.

WJQ1@seiang11g>select count(*) from dba_objects;

select count(*) from dba_objects

                     *

ERROR at line 1:

ORA-00942: table or view does not exist

SYS@seiang11g>

SYS@seiang11g>grant select any dictionary to wjq2;

Grant succeeded.

WJQ2@seiang11g>select count(*) from dba_objects;

  COUNT(*)

----------

     86994

WJQ2@seiang11g>exec wjq1.proc_wjq1;

BEGIN wjq1.proc_wjq1; END;

           *

ERROR at line 1:

ORA-06550: line 1, column 12:

PLS-00905: object WJQ1.PROC_WJQ1 is invalid

ORA-06550: line 1, column 7:

PL/SQL: Statement ignored

通過上面的實驗結果發(fā)現(xiàn):wjq2用戶擁有dba_objects對象訪問權限,同時也有執(zhí)行proc_wjq1的權限,但是執(zhí)行的時候卻報錯,認為對象無效。這是為什么呢?唯一的原因就是因為wjq1用戶失去了dba_objects對象的權限,而wjq2在調(diào)用proc_wjq1時使用的是dba_objects的權限。

以上案例一的實驗介紹了Oracle在存儲過程中使用的權限配置的“定義者權限”。簡單的說,當執(zhí)行一個程序體(存儲過程、函數(shù)和包等)的時候,方法體內(nèi)部使用的權限體系為當前該程序體定義者的權限體系,而與調(diào)用方法的用戶無關。存儲過程proc_wjq1無論是哪一個用戶執(zhí)行,權限體系都是該存儲過程的定義者wjq1的權限。

定義者權限是Oracle使用的默認權限選擇方式,在使用的時候很方便。調(diào)用者只要擁有簡單的對象執(zhí)行權限就可以了,無需顧及自己是否擁有權限訪問方法中使用的對象。

案例一對定義者權限通過實驗進行了分析,調(diào)用者權限的含義就相對容易理解了。調(diào)用者權限體系就是執(zhí)行方法體的時候,使用的權限按照調(diào)用者權限體系來判斷。一個方法的執(zhí)行,調(diào)用者除了要擁有執(zhí)行該方法的權限,還要擁有該方法中使用對象的權限才可以。

 

下面案例二通過實驗對調(diào)用者權限作出詳細的分析:

案例二:調(diào)用者權限

接著上面案例一的實驗環(huán)境。注意,此時wjq1用戶沒有select any dictionary權限,而wjq2有。

WJQ1@seiang11g>create or replace procedure proc_wjq1_1 is

  2  i number;

  3  begin

  4     select count(*) into i from dba_objects;

  5     dbms_output.put_line(to_char(i));

  6  end;

  7  /

Warning: Procedure created with compilation errors.

WJQ1@seiang11g>

WJQ1@seiang11g>select name,line,text from user_errors;

NAME                  LINE TEXT

--------------- ---------- --------------------------------------------------

PROC_WJQ1_1              4 PL/SQL: ORA-00942: table or view does not exist

PROC_WJQ1_1              4 PL/SQL: SQL Statement ignored 

查看報錯信息,還是因為wjq1沒有dba_objects的權限,所以創(chuàng)建過程失敗。

此時,如果在方法定義上加入authid current_user關鍵字,就可以將存儲過程變化為調(diào)用者權限。

WJQ1@seiang11g>create or replace procedure proc_wjq1_1 authid current_user is

  2  i number;

  3  begin

  4     select count(*) into i from dba_objects;

  5     dbms_output.put_line(to_char(i));

  6  end;

  7  /

Warning: Procedure created with compilation errors.

WJQ1@seiang11g>

WJQ1@seiang11g>select name,line,text from user_errors;

NAME                  LINE TEXT

--------------- ---------- --------------------------------------------------

PROC_WJQ1_1              4 PL/SQL: ORA-00942: table or view does not exist

PROC_WJQ1_1              4 PL/SQL: SQL Statement ignored 

顯然,還在因為wqj1用戶沒有權限訪問dba_objects而報錯,畢竟不管是什么體系,wjq1目前是沒有對象權限的創(chuàng)建過程是不會成功的。不過,為了實驗成功,還是要讓wjq1能順利創(chuàng)建proc_wjq1_1過程。

SYS@seiang11g>grant select any dictionary to wjq1;

Grant succeeded.

WJQ1@seiang11g>create or replace procedure proc_wjq1_1 authid current_user is

  2  i number;

  3  begin

  4     select count(*) into i from dba_objects;

  5     dbms_output.put_line(to_char(i));

  6  end;

  7  /

Procedure created. 

WJQ1@seiang11g>

WJQ1@seiang11g>grant execute on proc_wjq1_1 to wjq2;

Grant succeeded.

切換到wjq2用戶,注意此時它是擁有select any dictionary權限的。

WJQ2@seiang11g>select count(*) from dba_objects;

  COUNT(*)

----------

     86995

WJQ2@seiang11g>exec wjq1.proc_wjq1_1;

86995

PL/SQL procedure successfully completed. 

此時,wjq2執(zhí)行過程成功。因為此時wjq1和wjq2都擁有select any dictionary權限,所以即使在調(diào)用者權限下,也是會成功的。此時,如果收回wjq2上的權限,結果會如何呢?

SYS@seiang11g>revoke select any dictionary from wjq2;

Revoke succeeded.

WJQ2@seiang11g>select count(*) from dba_objects;

select count(*) from dba_objects

                     *

ERROR at line 1:

ORA-00942: table or view does not exist

WJQ2@seiang11g>exec wjq1.proc_wjq1;

BEGIN wjq1.proc_wjq1; END;

           *

ERROR at line 1:

ORA-06550: line 1, column 12:

PLS-00905: object WJQ1.PROC_WJQ1 is invalid

ORA-06550: line 1, column 7:

PL/SQL: Statement ignored

此時,就看出調(diào)用者權限的差異了。wjq1始終有dba_objects的權限,而wjq2在之后被回收了select any dictionary的權限。如果是定義者權限,wjq2調(diào)用proc_wjq1_1是沒有問題的。但是此時報錯,說明此處使用的是wjq2的調(diào)用者權限。

       通過上述兩個案例,分別通過實驗對定義者權限和使用者權限進行了分析,想必大家已經(jīng)有了比較深刻的認識和理解了,但是很多時候,我們都會使用存儲過程Procedure來實現(xiàn)一些腳本功能。通過Procedure來實現(xiàn)一些數(shù)據(jù)庫相關的維護、開發(fā)工作,可以大大提高我們?nèi)粘9ぷ餍?。下面?shù)據(jù)庫運維過程中有這樣一種情況需要我們DBA去處理,實際的問題這樣的:


      同一個數(shù)據(jù)庫中有多個Schema的內(nèi)容相同,用于不同的測試目的。一些開發(fā)同步任務促使編寫一個程序來實現(xiàn)Schema內(nèi)部或者之間對象操作。從軟件版本角度看,維護一份工具腳本是最好的方法,可以避免由于修改造成的版本錯亂現(xiàn)象。如何通過一個存儲過程腳本,在不同Schema下執(zhí)行效果不同就成了我們需要考慮的問題?


       將上述問題簡化如下:在
Schema A里面包括一個存儲過程Proc,A中還有一張數(shù)據(jù)表T1。在Proc代碼中,包括了對表T1的操作內(nèi)容。而Schema B中也存在一個數(shù)據(jù)表T1,并且B擁有一個名為Proc的私有同義詞synonym指向A.Proc。問題是如何讓Proc根據(jù)執(zhí)行的Schema的不同,訪問不同Schema中數(shù)據(jù)表?換句話說,就是如果是Schema A調(diào)用Proc程序包,操作的就是Schema A里面的數(shù)據(jù)表T1。如果B調(diào)用Proc程序包,就操作Schema B里面的數(shù)據(jù)表T1。

為了對上述問題有一個明確的處理方法,下面通過以下示例進行模擬實驗:

SYS@seiang11g>select * from v$version;

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

PL/SQL Release 11.2.0.4.0 - Production

CORE    11.2.0.4.0      Production

TNS for Linux: Version 11.2.0.4.0 - Production

NLSRTL Version 11.2.0.4.0 - Production

SYS@seiang11g>create user wjq1 identified by wjq1 default tablespace seiang;

User created.

SYS@seiang11g>create user wjq2 identified by wjq2 default tablespace seiang;

User created.

SYS@seiang11g>grant connect,resource,create procedure,create synonym to wjq1,wjq2;

Grant succeeded.

SYS@seiang11g>select * from dba_sys_privs where grantee in ('WJQ1','WJQ2');

GRANTEE                        PRIVILEGE                                ADM

------------------------------ ---------------------------------------- ---

WJQ1                           CREATE SYNONYM                           NO

WJQ2                           UNLIMITED TABLESPACE                     NO

WJQ2                           CREATE SYNONYM                           NO

WJQ1                           UNLIMITED TABLESPACE                     NO

WJQ2                           CREATE PROCEDURE                         NO

WJQ1                           CREATE PROCEDURE                         NO

6 rows selected. 

在Schema wjq1下面創(chuàng)建數(shù)據(jù)表和相應的存儲過程。

 WJQ1@seiang11g>create table tab_wjq(name varchar2(20));

Table created.

WJQ1@seiang11g>create or replace procedure proc_wjq1(v_name varchar2) is

  2  begin

  3     insert into tab_wjq values(v_name);

  4     commit;

  5  end proc_wjq1;

  6  /

Procedure created.

Schema wjq1進行執(zhí)行存儲過程

WJQ1@seiang11g>exec proc_wjq1('wjq');

PL/SQL procedure successfully completed.

WJQ1@seiang11g>select * from tab_wjq;

NAME

--------------------

wjq 

將過程proc_wjq1的權限賦予Schema wjq2

 WJQ1@seiang11g>grant execute on proc_wjq1 to wjq2;

Grant succeeded. 

另外創(chuàng)建Schema wjq2數(shù)據(jù)表對象,并且包括同義詞對象。

 WJQ2@seiang11g>create table tab_wjq(name varchar2(20));

Table created.

WJQ2@seiang11g>create synonym proc_wjq1 for wjq1.proc_wjq1;

Synonym created.

WJQ2@seiang11g>select * from user_synonyms;

SYNONYM_NAME    TABLE_OWNER     TABLE_NAME           DB_LINK

--------------- --------------- -------------------- ------------------------------

PROC_WJQ1       WJQ1            PROC_WJQ1 

進行默認情況測試,在Schema wjq2中調(diào)用存儲過程proc_wjq1,查看操作的是哪一個Schema下的數(shù)據(jù)表

WJQ2@seiang11g>exec proc_wjq1('seiang');

PL/SQL procedure successfully completed.

WJQ2@seiang11g>select * from tab_wjq;

no rows selected

Schema wjq2中數(shù)據(jù)表tab_wjq沒有數(shù)據(jù),查看Schema wjq1中數(shù)據(jù)表情況:

WJQ1@seiang11g>select * from tab_wjq;

NAME

--------------------

wjq

seiang 

上述實驗說明:在默認情況下,不同Schema對象調(diào)用相同存儲過程,其中涉及到的對象都是相同的。也就是Oracle存儲過程中的“定義者權限”。一旦用戶擁有執(zhí)行存儲過程的權限,就意味著在執(zhí)行體中,使用的是定義者的權限體系。

       那么這個問題似乎是沒有辦法。執(zhí)行體指向的是Schema wjq1的數(shù)據(jù)表tab_wjq。

與定義者權限對應的就是“調(diào)用者權限”。也就說,對用戶是否可以執(zhí)行該程序體中的對象,完全取決于執(zhí)行調(diào)用用戶系統(tǒng)權限和對象權限(注意:非角色權限)。大膽的猜想,如果使用調(diào)用者權限,從執(zhí)行用戶權限角度看,是不是可以直接訪問自己Schema中的對象了?下面通過實驗進行驗證:

 WJQ1@seiang11g>create or replace procedure proc_wjq1(v_name varchar2) authid current_user is

  2  begin

  3     insert into tab_wjq values(v_name);

  4     commit;

  5  end proc_wjq1;

  6  /

Procedure created.

在用戶wjq1中進行實驗,結果:

WJQ1@seiang11g>exec proc_wjq1('wjqbest');

PL/SQL procedure successfully completed.

WJQ1@seiang11g>select * from tab_wjq;

NAME

--------------------

wjq

seiang

wjqbest

轉換到用戶wjq2中,進行實驗:

 WJQ2@seiang11g>exec proc_wjq1('seiangbest');

PL/SQL procedure successfully completed.

WJQ2@seiang11g>select * from tab_wjq;

NAME

--------------------

seiangbest 

從上面的實驗結果可以發(fā)現(xiàn):在調(diào)用者權限模式下,可以實現(xiàn)調(diào)用Schema下數(shù)據(jù)表優(yōu)先的效果。如果此時Schema wjq2中沒有數(shù)據(jù)表tab_wjq,結果又會如何呢?

 WJQ2@seiang11g>drop table tab_wjq;

Table dropped.

WJQ2@seiang11g>exec proc_wjq1('hahaha');

BEGIN proc_wjq1('hahaha'); END;

*

ERROR at line 1:

ORA-00942: table or view does not exist

ORA-06512: at "WJQ1.PROC_WJQ1", line 3

ORA-06512: at line 1

如果wjq2用戶擁有wjq1用戶下的數(shù)據(jù)表tab_wjq的權限,結果又會如何呢?

 WJQ1@seiang11g>grant all on tab_wjq to wjq2;

Grant succeeded.

WJQ2@seiang11g>select * from wjq1.tab_wjq;

NAME

--------------------

wjq

seiang

wjqbest

WJQ2@seiang11g>exec proc_wjq1('hahaha');

BEGIN proc_wjq1('hahaha'); END;

*

ERROR at line 1:

ORA-00942: table or view does not exist

ORA-06512: at "WJQ1.PROC_WJQ1", line 3

ORA-06512: at line 1

從上面的結果發(fā)現(xiàn),即使wjq2擁有wjq1下數(shù)據(jù)表tab_wjq的權限,在使用調(diào)用者權限時,也是只能操作自己Schema下的對象。所以定義者權限和調(diào)用者權限,是Oracle存儲過程中兩個重要的概念對象,一些麻煩場景下應用往往有不錯的效果。

感謝各位的閱讀!關于“Oracle中定義者權限和調(diào)用者權限的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI