Oracle儲存過程物件(package,procedure etc...) 呼叫許可權 ----20180206
阿新 • • 發佈:2019-01-25
在一些技術論壇裡面,常常看到有朋友問這種問題: 為什麼我的使用者具有DBA許可權,卻無法在儲存過程裡面建立一張普通表呢?
下面就結合具體案例來談談這個問題:
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 許可權!
用此使用者建立一個儲存過程:
create or replace procedure p_CreateTable
as
begin
execute immediate ‘create table test_tb(id number)‘;
end p_CreateTable;
/
Procedure created.
執行時會發現,系統提示許可權不足(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,也不能建立表。即 role在儲存過程中不可見!
查閱資料發現:
Oracle8i以前的版本,所有已編譯儲存物件,包括packages, procedures, functions, triggers, views等,只能以定義者(Definer)身份解析執行;
而Oracle8i及其後的新版本,Oracle引入呼叫者(invoker)許可權,使得物件可以以呼叫者身份和許可權執行。
遇到這種情況,通常解決方法是進行顯式的系統許可權: grant create table to eric;但是,此方法太笨,因為有可能執行一個儲存過程,
需要很多不同許可權(oracle對許可權劃分粒度越來越細)。
最好的方法是,利用 oracle 提供的方法,在建立儲存過程時,加入 Authid Current_User 條件進行許可權分配。
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要執行A使用者的某儲存過程,傳統的解決方案是:
A使用者將此儲存過程的執行許可權賦予B使用者:
grant execute on p_test to B;
在B使用者下建立一個同義詞:
create synonym p_test for a.p_test;
然後B使用者就可以直接執行p_test了.
但是,如果使用 Authid Current_User 選項,在建立時給呼叫者授權,就簡單多了!
下面就結合具體案例來談談這個問題:
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 許可權!
用此使用者建立一個儲存過程:
create or replace procedure p_CreateTable
as
begin
execute immediate ‘create table test_tb(id number)‘;
end p_CreateTable;
/
Procedure created.
執行時會發現,系統提示許可權不足(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,也不能建立表。即 role在儲存過程中不可見!
查閱資料發現:
Oracle8i以前的版本,所有已編譯儲存物件,包括packages, procedures, functions, triggers, views等,只能以定義者(Definer)身份解析執行;
而Oracle8i及其後的新版本,Oracle引入呼叫者(invoker)許可權,使得物件可以以呼叫者身份和許可權執行。
遇到這種情況,通常解決方法是進行顯式的系統許可權: grant create table to eric;但是,此方法太笨,因為有可能執行一個儲存過程,
需要很多不同許可權(oracle對許可權劃分粒度越來越細)。
最好的方法是,利用 oracle 提供的方法,在建立儲存過程時,加入 Authid Current_User 條件進行許可權分配。
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要執行A使用者的某儲存過程,傳統的解決方案是:
A使用者將此儲存過程的執行許可權賦予B使用者:
grant execute on p_test to B;
在B使用者下建立一個同義詞:
create synonym p_test for a.p_test;
然後B使用者就可以直接執行p_test了.
但是,如果使用 Authid Current_User 選項,在建立時給呼叫者授權,就簡單多了!