您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Oracle中定義者權限和調用者權限的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
定義者權限:定義者權限指使用它所有者的權限,而不是當前用戶來執行過程。因此,你可以限制用戶執行的數據庫操作,允許他們僅通過運行定義者權限的過程和函數訪問數據。創建過程、函數和程序包的默認權限是定義者權限。
調用者權限:在當前的用戶模式下用當前的用戶權限來執行過程。換句話說,就是調用者的權限過程并不與某個特定的用戶或模式綁定。調用者權限程序可以使應用程序開發人員很容易的將應用邏輯集中起來,即使底層的數據在用戶和模式中被劃分。創建時需要顯式使用AUTHID CURRENT_USER來定義調用者過程。
(注意:在閱讀下面案例的時候注意sqlplus的使用的不同用戶)
具體演示如下所示:
1、創建兩個測試用戶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,創建兩個過程proc_definer和proc_invoker
過程1:定義者權限,為創建過程的默認權限
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下分別執行定義者權限和使用者權限的過程
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創建的兩個過程授權給用戶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下分別調用兩個過程,結果顯示在調用者權限下,程序在當前用戶下用當前用戶的權限執行
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.
通過上面的簡單的演示,已經對定義者權限和調用者權限有了一定的認識和理解,但是僅僅初步的了解在生產環境中,遇到實際的案例還是有點摸不著頭腦,下面通過兩個實際的案例來分析定義者權限和調用者權限,更加深入的去理解它們的使用方法。
在存儲過程中,時常會遇到這樣一種場景:用戶A下有一個存儲過程(或者函數體、包體)Proc,在過程中間引用了對象obj。在編譯存儲過程時,是要求用戶A有對象obj的權限的,如果沒有,則系統報編譯錯誤。當成功進行編譯之后,用戶A將執行execute存儲過程Proc的權限賦給了用戶B。但是用戶B不一定擁有對象obj的使用權限,那么問題就來了,此時用戶B能否成功執行存儲過程Proc呢?
下面我們通過實驗來進行驗證:
接著上面例子,用戶wjq1和wjq2除了擁有connect和resource角色的權限之外,出于實驗的目的,我們將select any dictionary的系統權限賦予給用戶wjq1
SYS@seiang11g>grant select any dictionary to wjq1;
Grant succeeded.
select any dictionary的系統權限意味著用戶可以訪問數據字典視圖層面的視圖中的對象數據。
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也可以執行編譯操作。
案例一:定義者權限
緊接著上面的實驗,對于wjq2用戶,只有執行wjq1用戶下proc_wjq1存儲過程權限,但是沒有訪問dba_objects視圖權限,看實際效果。
用戶wjq2只具有基本的connect和resource權限。將proc_wjq1過程的執行權限授權給wjq2
WJQ1@seiang11g>grant execute on proc_wjq1 to wjq2;
Grant succeeded.
之后,檢查wjq2用戶下,過程proc_wjq1的執行情況
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權限,但是因為擁有執行proc_wjq1的權限,在執行proc_wjq1的時候,也是可以在方法中訪問到dba_objects。顯然,此時wjq2在執行proc_wjq1上應用了wjq1用戶對于dba_objects的權限,也就是對象定義者的權限。
為了進一步證明結果的準確性,下面將繼續進行實驗變化來演示
當定義者權限失去時,即使調用者擁有權限也是無用的(也就是說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
通過上面的實驗結果發現:wjq2用戶擁有dba_objects對象訪問權限,同時也有執行proc_wjq1的權限,但是執行的時候卻報錯,認為對象無效。這是為什么呢?唯一的原因就是因為wjq1用戶失去了dba_objects對象的權限,而wjq2在調用proc_wjq1時使用的是dba_objects的權限。
以上案例一的實驗介紹了Oracle在存儲過程中使用的權限配置的“定義者權限”。簡單的說,當執行一個程序體(存儲過程、函數和包等)的時候,方法體內部使用的權限體系為當前該程序體定義者的權限體系,而與調用方法的用戶無關。存儲過程proc_wjq1無論是哪一個用戶執行,權限體系都是該存儲過程的定義者wjq1的權限。
定義者權限是Oracle使用的默認權限選擇方式,在使用的時候很方便。調用者只要擁有簡單的對象執行權限就可以了,無需顧及自己是否擁有權限訪問方法中使用的對象。
案例一對定義者權限通過實驗進行了分析,調用者權限的含義就相對容易理解了。調用者權限體系就是執行方法體的時候,使用的權限按照調用者權限體系來判斷。一個方法的執行,調用者除了要擁有執行該方法的權限,還要擁有該方法中使用對象的權限才可以。
下面案例二通過實驗對調用者權限作出詳細的分析:
案例二:調用者權限
接著上面案例一的實驗環境。注意,此時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的權限,所以創建過程失敗。
此時,如果在方法定義上加入authid current_user關鍵字,就可以將存儲過程變化為調用者權限。
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目前是沒有對象權限的創建過程是不會成功的。不過,為了實驗成功,還是要讓wjq1能順利創建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執行過程成功。因為此時wjq1和wjq2都擁有select any dictionary權限,所以即使在調用者權限下,也是會成功的。此時,如果收回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
此時,就看出調用者權限的差異了。wjq1始終有dba_objects的權限,而wjq2在之后被回收了select any dictionary的權限。如果是定義者權限,wjq2調用proc_wjq1_1是沒有問題的。但是此時報錯,說明此處使用的是wjq2的調用者權限。
通過上述兩個案例,分別通過實驗對定義者權限和使用者權限進行了分析,想必大家已經有了比較深刻的認識和理解了,但是很多時候,我們都會使用存儲過程Procedure來實現一些腳本功能。通過Procedure來實現一些數據庫相關的維護、開發工作,可以大大提高我們日常工作效率。下面數據庫運維過程中有這樣一種情況需要我們DBA去處理,實際的問題這樣的:
同一個數據庫中有多個Schema的內容相同,用于不同的測試目的。一些開發同步任務促使編寫一個程序來實現Schema內部或者之間對象操作。從軟件版本角度看,維護一份工具腳本是最好的方法,可以避免由于修改造成的版本錯亂現象。如何通過一個存儲過程腳本,在不同Schema下執行效果不同就成了我們需要考慮的問題?
將上述問題簡化如下:在Schema A里面包括一個存儲過程Proc,A中還有一張數據表T1。在Proc代碼中,包括了對表T1的操作內容。而Schema B中也存在一個數據表T1,并且B擁有一個名為Proc的私有同義詞synonym指向A.Proc。問題是如何讓Proc根據執行的Schema的不同,訪問不同Schema中數據表?換句話說,就是如果是Schema A調用Proc程序包,操作的就是Schema A里面的數據表T1。如果B調用Proc程序包,就操作Schema B里面的數據表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下面創建數據表和相應的存儲過程。
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進行執行存儲過程
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.
另外創建Schema wjq2數據表對象,并且包括同義詞對象。
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中調用存儲過程proc_wjq1,查看操作的是哪一個Schema下的數據表
WJQ2@seiang11g>exec proc_wjq1('seiang');
PL/SQL procedure successfully completed.
WJQ2@seiang11g>select * from tab_wjq;
no rows selected
Schema wjq2中數據表tab_wjq沒有數據,查看Schema wjq1中數據表情況:
WJQ1@seiang11g>select * from tab_wjq;
NAME
--------------------
wjq
seiang
上述實驗說明:在默認情況下,不同Schema對象調用相同存儲過程,其中涉及到的對象都是相同的。也就是Oracle存儲過程中的“定義者權限”。一旦用戶擁有執行存儲過程的權限,就意味著在執行體中,使用的是定義者的權限體系。
那么這個問題似乎是沒有辦法。執行體指向的是Schema wjq1的數據表tab_wjq。
與定義者權限對應的就是“調用者權限”。也就說,對用戶是否可以執行該程序體中的對象,完全取決于執行調用用戶系統權限和對象權限(注意:非角色權限)。大膽的猜想,如果使用調用者權限,從執行用戶權限角度看,是不是可以直接訪問自己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
從上面的實驗結果可以發現:在調用者權限模式下,可以實現調用Schema下數據表優先的效果。如果此時Schema wjq2中沒有數據表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用戶下的數據表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
從上面的結果發現,即使wjq2擁有wjq1下數據表tab_wjq的權限,在使用調用者權限時,也是只能操作自己Schema下的對象。所以定義者權限和調用者權限,是Oracle存儲過程中兩個重要的概念對象,一些麻煩場景下應用往往有不錯的效果。
感謝各位的閱讀!關于“Oracle中定義者權限和調用者權限的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。