學習Oracle PL/SQL -執行權限模型(AUTHID DEFINER、AUTHID CURRENT_USER)

來源《Oracle plsql 程序設計》
寫存儲過程時經常由於執行權限導致得不到想要的數據,現在詳細看一下;
Oracle數據庫爲PL/SQL程序提供了兩種對象許可模型,默認的是定義者權限(AUTHID DEFINER),使用這種模型,存儲過程是運行在他的所有者權限下的;

1 定義者權限模型(AUTHID DEFINER)

執行存儲過程前要前,程序要先編譯並且保存到數據庫中。一個程序通常保存在一個模式或者說一個數據庫用戶下,程序中可能會用到其他用戶下的對象。

定義者權限模型的規則

1.程序中的任何外部引用都必須在編譯時被解析,所使用的權限是編譯時所在模式被直接賦予的權限
2.在編譯存儲過程時,數據庫角色會被忽略。這個程序需要的所有權限都必須直接授予這個過程的定義者
3.當執行定義者權限模型編譯的過程時,過程執行的sql都是運行於擁有這個過程的模式的權限之下;
4.儘管編譯過程需要直接授權,可以把執行程序所需要的EXECUTE權限授予其他模式或角色;
使用定義者權限模型控制對底層數據的訪問:
所有的訂單處理數據放在OEData模式下;
所有的訂單處理代碼放在ODCode模式下,且編譯Order_Mgt的權限直接授予了OECode,這個包允許下訂單和取消訂單;
在這裏插入圖片描述
爲了保證正確更新訂單,不允許除了OEcode以外的其他任何模式直接訪問這個表。比如,加入Sam_Sales模式需要關閉舊訂單,他不能通過Close_Old_Orders執行刪除語句,必須通過調用Order_Mgt.cancel完成刪除訂單任務。

定義者權限模型的好處

1.能控制對底層結構的訪問,保證只能通過專門的程序接口這一種方式修改表內容;
2.由於plsql引擎不必在運行時檢查是否有權限,應用程序的性能顯著改善;
3.不用擔心搞錯表;

定義者權限模型的缺點
我的表在哪

開發人員通常使用屬於其他模式的表編寫代碼,並且爲這些表或視圖創建公有別名,從而隱藏模式信息。然後通過數據庫角色授權。,這種做法造成一些問題;
假如組織內部都是通過角色分配對對象的訪問權限。有一個accounts表,其實是一個基於其他模式下表的同義詞。當在sqlplus中執行如下語句時沒有什麼問題:

SELECT account#,name FROM accounts;

而在過程中使用這張表時卻報錯:

CREATE OR REPLACE PROCEDURE show_accounts
IS
BEGIN
	FOR rec IN (SELECT account#,name FROM accounts)
	LOOP
		DBMS_OUTPUT.PUT_LINE(rec.name);
	END LOOP;
END;

提示ACCOUNTS必須被定義。
造成問題的原因是accounts實際是屬於另一個模式的表,解決問題需要讓DBA授權,才能完成任務。

動態SQL和定義者權限

另一個問題出在執行動態sql上,加入有這樣一個過程,被用來執行DDL語句:

PROCEDUTE execDDL(ddl_string IN VARCHAR2)
IS
BEGIN
	EXECUTE IMMEDIATE ddl_string;
EXCEPTION結果是
  WHEN OTHERS
  THEN 
      DBMS_OUTPUT.PUT_LINE('Dynamic SQL Failure:'||SQLERRM);
      DBMS_OUTPUT.PUT_LINE('   on statement:"'|| ddl_strint ||'"');
      RAISE;
END;

這個程序在自己用戶下測試執行沒有問題。在COMMON用戶下編譯後,共享給其他人使用。結果是執行的創建,刪除,修改的所有對象都在COMMON用戶下,除非創建表時指定了表的模式且COMMON用戶有創建任何表的權限。

2 調用者權限模型(AUTHID CURRENT_USER)

當程序使用運行程序的人的權限而不是程序所有者的權限時,應該選用 調用者權限模型 。執行權限模型爲調用者的程序,程序中的sql語句的外部引用都會根據調用者的權限進行解析,而不再是根據擁有這個程序或定義這個程序的模式進行解析。
在這裏插入圖片描述
如上圖所示,當程序使用的是調用者權限模型編譯在一個代碼庫中,一個東北方的用戶執行代碼庫中的代碼時,就會自動使用自己模式下的表。

調用者權限的語法

就是在程序頭部IS或者AS關鍵字之前添加子句AUTHID CURRENT_USER就可以了。
例如上面的執行DDL語句的程序,用調用者權限定義就是這樣:

PROCEDURE 	execddl(ddl_in in VARCHAR2)
	AUTHID CURRENT_USER
IS
BEGIN
	EXECUTE IMMEDIATE ddl_in;
END;

關鍵子AUTHID CURRENT_USER 表明當程序執行時,應該在調用者的權限下執行,而不是定義者權限。

調用者權限的規則和限制

1.調用者模型需要顯示指定關鍵字AUTHID CURRENT_USER,默認是定義者權限模型;
2.調用者權限模型是在程序運行時刻才根據調用者的權限對sql使用的數據庫對象進行解析;
3.使用調用者權限模型時,只要調用者權限模型不是從定義者權限程序中調用的,運行時角色就有效
4.AUTHID子句只能用於一個單獨的程序的頭部、包規範或者對象類型規範。不能對包裏的個別程序或對象類型的方法使用AUTHID子句。所以整個包都是調用者或定義者權限。如果包裏需要包含兩種執行權限模型,那麼就需要使用兩個包。
5.調用者權限對外部引用的解析使用於下列語句:

--SELECT 、INSERT、UPDATE、MERGE、DELETE數據操作語言
--LOCK TABLE事務控制語言
--OPEN 和 OPEN FOR 遊標控制語句
--EXECUTE IMMEDIATE 和 OPEN FOR USING 動態SQL語句
--使用DBMS_SQL.PARSE解析的SQL語句

6.定義者權限總是在編譯時刻解析PL/SQL程序和對象類型方法中的外部引用;
7.可以通過調用者權限修改 對於靜態的外部數據元素引用的解析

3.組合權限模型

如果在一個定義者權限模型的程序中調用了一個調用者權限模型的程序,會發生什麼:
1.如果是定義者權限的程序 調用 調用者權限的程序 ,被調用的程序執行時使用的是調用程序所擁有的權限
2.如果是調用者權限的程序 調用 定義者權限的程序, 當被調用的程序運行時使用的是被調用程序所有這擁有的權限。一旦控制返回給調用者,又會恢復調用這權限。
總的來說就是定義者權限 要比 調用者權限 更強。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章