我在一些技術(shù)論壇里面,常常看到有朋友問這種問題: 為什么我的用戶具有DBA權(quán)限,卻無法在存儲過程里面創(chuàng)建一張普通表呢?
下面就結(jié)合具體案例來談談這個問題:
SQL> conn eric/eric;
Connected. SQL> select * from dba_role_privs where grantee=‘ERIC‘;
GRANTEE GRANTED_ROLE ADM DEF ------------------------------ ------------------------------ --- --- ERIC DBA NO YES ERIC CONNECT NO YES ERIC RESOURCE NO YES ERIC RECOVERY_CATALOG_OWNER NO YES 可以看到,用戶eric擁有 DBA 權(quán)限!
用此用戶創(chuàng)建一個存儲過程:
create or replace procedure p_CreateTable
as begin execute immediate ‘create table test_tb(id number)‘; end p_CreateTable; / Procedure created.
運行時會發(fā)現(xiàn),系統(tǒng)提示權(quán)限不足(insufficient privileges)! SQL> exec p_CreateTable;
BEGIN p_CreateTable; END; * ERROR at line 1: ORA-01031: insufficient privileges ORA-06512: at "ERIC.P_CREATETABLE", line 3 ORA-06512: at line 1 由上可以看到,即使擁有DBA role,也不能創(chuàng)建表。
即 role在存儲過程中不可見!
查閱資料發(fā)現(xiàn): Oracle8i以前的版本,所有已編譯存儲對象,包括packages, procedures, functions, triggers, views等,只能以定義者(Definer)身份解析運行;
而Oracle8i及其后的新版本,Oracle引入調(diào)用者(invoker)權(quán)限,使得對象可以以調(diào)用者身份和權(quán)限執(zhí)行。
遇到這種情況,通常解決方法是進行顯式的系統(tǒng)權(quán)限: grant create table to eric; 但是,此方法太笨,因為有可能執(zhí)行一個存儲過程,需要很多不同權(quán)限(oracle對權(quán)限劃分粒度越來越細)。
最好的方法是,利用 oracle 提供的方法,在創(chuàng)建存儲過程時,加入 Authid Current_User 條件進行權(quán)限分配。
create or replace procedure p_CreateTable Authid Current_User
as begin execute immediate ‘create table test_tb(id number)‘; end p_CreateTable; / Procedure created.
SQL> exec p_CreateTable;
PL/SQL procedure successfully completed. SQL> desc test_tb Name Null? Type ----------------------------------------- -------- ---------------------------- ID NUMBER 成功啦?。?! 由此可以引申出一個問題: 如果用戶B要執(zhí)行A用戶的某存儲過程,傳統(tǒng)的解決方案是:
A用戶將此存儲過程的執(zhí)行權(quán)限賦予B用戶:
grant execute on p_test to B; 在B用戶下創(chuàng)建一個同義詞:
create synonym p_test for a.p_test; 然后B用戶就可以直接執(zhí)行p_test了.
但是,如果使用 Authid Current_User 選項,在創(chuàng)建時給調(diào)用者授權(quán),就簡單多了! |
|