角色(數據庫權限集)與存儲過程、函數和數據包之間的交互方式是Oracle安全模型中最難以處理的一個部分。Oracle中的對象權限可以直接或通過角色間接授予用戶。 假設一個HR用戶向用戶ABEL授予EMPLOYEES表的一些許可:
GRANT select, insert, update, delete
這個語句直接把上述四個權限授予給用戶ABEL。另一方面,假設一名HR用戶這樣做:
GRANT select, insert, update, delete ON employees TO hr_role;
如果ABEL已被授予HR_ROLE角色,那麼他現在通過這個角色就直接擁有了以上權限。
不管使用哪種方法,現在ABEL都擁有了HR.EMPLOYEES表的SELECT權限。如果ABEL通過SELECT語句直接從表中選擇數據,那麼他如何獲得許可並不重要。
但是,如果ABEL試圖建立從這個表中選擇的存儲過程、函數或數據包,那麼他是直接獲得許可,還是通過角色取得許可就存在很大差異。
Oracle要求直接向用戶授予一個存儲過程中的非擁有對象許可。在編輯過程中角色被臨時關閉,用戶不能訪問授予給他們的任何內容。這樣做是出於性能和安全考慮。
角色可以通過SET ROLE命令動態激活和禁用,如果Oracle需要不斷檢查哪個角色和許可當前處於激活狀態,則會帶來巨大的管理負擔。
下面的代碼是一個更新HR雇員文件的簡短存儲過程(這段代碼用一個同義字EMPLOYEES來代表HR.EMPLOYEES)。當ABEL在第一種情況下試圖用直接權限編輯這個文件時,編輯取得成功;當他在第二種情況下僅用間接權限編輯時,編輯失敗。
CREATE OR REPLACE PROCEDURE update_emp (
p_employee_id IN NUMBER
,p_salary IN NUMBER
)
AS
v_department_idemployees.department_id%TYPE;
BEGIN
SELECT department_id INTO v_department_id
FROM employees
WHERE employee_id = p_employee_id;
UPDATE employees
SET salary = p_salary
WHERE employee_id = p_employee_id;
IF v_department_id = 100 THEN
UPDATE local_employees
SET salary = p_salary
WHERE employee_id = p_employee_id;
END IF;
END;
/
有趣的是,向PUBLIC授予許可和直接授予所有用戶許可相同。PUBLIC常被認為是一個角色,但它並不是一個角色。它是一個用戶集而不是一個許可集。如果向PUBLIC授權HR.EMPLOYEES的許可,ABEL將能夠建立他自己的存儲過程。雖然在EMPLOYEES表中我們不推薦這樣做,但任何授予給PUBLIC的表都可以自由地在存儲過程中應用。