כל תוכנית PLSQL רצה תחת סט השראות מסויים. באופן דיפולטיבי, רצה התוכנית תחת ההרשאות של היוזר אשר הגדיר אותה (Definer) ולחילופין, החל מגרסת 8i, תוכל לרוץ תחת ההרשאות של היוזר אשר מריץ אותה (Invoker).
לדוגמא – יוזר sales_1 מייצר פרוצדורה אשר נועדה לעדכן את טבלת הלקוחות בסכמה שלו, את ההרשאות להרצת הפרוצדורה הוא מעביר ליוזר sales_2.
Definer Right – כאשר יוזר sales_2 מריץ את הפרוצדורה, באופן דיפולטיבי היא רצה תחת סט ההרשאות של היוצר שלה sales_1. משמעות הדבר – ל sales_2 יש את היכולת לעדכן את טבלת הלקוחות של יוזר sales_1 באמצעות הפרוצדורה, עם זאת sales_2 לא יכול לעדכן את טבלת הלקוחות ישירות.
Invoker Right – כאשר יוזר sales_2 מריץ את הפרוצדורה, היא רצה תחת סט ההרשאות שלו. משמעות הדבר – לפרוצדורה לא יהיו את ההרשאות לעדכן את הטבלה השייכת ל sales_1, עם זאת אם ליוזר sales_2 תהיה טבלה תחת אותו שם, הפרוצדורה תוכל לשמש אותו.
Definer Right
תחת יוזר sales1 נייצר פרוצדורה בשם customers_proc על טבלת customers, באמצעות פרוצדורה זו נוכל להכניס שורה חדשה או לעדכן שורה קיימת בטבלה.
SYS > CONN sales1/sales1 Connected. SALES1 > SALES1 > DROP TABLE customers ; Table dropped. SALES1 > SALES1 > CREATE TABLE customers 2 (id number, 3 name varchar2(25)) ; Table created. SALES1 > SALES1 > CREATE OR REPLACE PROCEDURE customers_proc 2 (p_code number, -- 1 is for insert, 2 is for update 3 p_id number, 4 p_name varchar2) 5 -- authid definer (By default Definer's rights) 6 IS 7 BEGIN 8 IF p_code = 1 THEN 9 INSERT INTO customers 10 VALUES (p_id , p_name) ; 11 DBMS_OUTPUT.PUT_LINE (sql%rowcount || ' row was inserted'); 12 ELSIF p_code = 2 THEN 13 UPDATE customers 14 SET name = p_name 15 WHERE id = p_id ; 16 DBMS_OUTPUT.PUT_LINE (sql%rowcount || ' rows was updated'); 17 END IF ; 18 END ; 19 / Procedure created. SALES1 > SALES1 > SET SERVEROUTPUT ON SALES1 > SALES1 > EXEC customers_proc (1, 1, 'Moshe') 1 row was inserted PL/SQL procedure successfully completed. SALES1 > SALES1 > SELECT * FROM customers ; ID NAME ---------- ------------------------- 1 Moshe SALES1 > SALES1 > EXEC customers_proc (2, 1, USER) 1 rows was updated PL/SQL procedure successfully completed. SALES1 > SALES1 > SELECT * FROM customers ; ID NAME ---------- ------------------------- 1 SALES1 SALES1 > SALES1 > COMMIT ; Commit complete.
כעת ניתן את ההרשאות על הפרוצדורה ליוזר sales2
SALES1 > GRANT EXECUTE ON customers_proc TO sales2 ; Grant succeeded. SALES1 > SALES1 > CONN sales2/sales2 Connected. SALES2 > SALES2 > SET SERVEROUTPUT ON SALES2 > SALES2 > EXEC sales1.customers_proc (1, 2, 'David') 1 row was inserted PL/SQL procedure successfully completed. SALES2 > SALES2 > EXEC sales1.customers_proc (2, 2, USER) 1 rows was updated PL/SQL procedure successfully completed. SALES2 > SALES2 > COMMIT ; Commit complete. SALES2 > SALES2 > CONN sales1/sales1 Connected. SALES1 > SALES1 > SELECT * FROM customers ; ID NAME ---------- ------------------------- 1 SALES1 2 SALES2
ניתן לראות כי ליוזר sales2 יש גישה מלאה לטבלה באמצעות הפרוצדורה.
Invoker Right
כעת נחזור על התהליך, אך הפעם נגדיר את הפרוצדורה לרוץ תחת סט ההרשאות של היוזר אשר מריץ אותה. ניתן לראות כי עבור יוזר sales1 דברים נותרו כפי שהיו
SALES1 > CONN sales1/sales1 Connected. SALES1 > SALES1 > DROP TABLE customers ; Table dropped. SALES1 > SALES1 > CREATE TABLE customers 2 (id number, 3 name varchar2(25)) ; Table created. SALES1 > SALES1 > CREATE OR REPLACE PROCEDURE customers_proc 2 (p_code number, -- 1 is for insert, 2 is for update 3 p_id number, 4 p_name varchar2) 5 AUTHID CURRENT_USER -- (Activate Invoker’s rights) 6 IS 7 BEGIN 8 IF p_code = 1 THEN 9 INSERT INTO customers 10 VALUES (p_id , p_name) ; 11 DBMS_OUTPUT.PUT_LINE (sql%rowcount || ' row was inserted'); 12 ELSIF p_code = 2 THEN 13 UPDATE customers 14 SET name = p_name 15 WHERE id = p_id ; 16 DBMS_OUTPUT.PUT_LINE (sql%rowcount || ' rows was updated'); 17 END IF ; 18 END ; 19 / Procedure created. SALES1 > SALES1 > SET SERVEROUTPUT ON SALES1 > SALES1 > EXEC customers_proc (1, 1, 'Moshe') 1 row was inserted PL/SQL procedure successfully completed. SALES1 > SALES1 > SELECT * FROM customers ; ID NAME ---------- ------------------------- 1 Moshe SALES1 > SALES1 > EXEC customers_proc (2, 1, USER) 1 rows was updated PL/SQL procedure successfully completed. SALES1 > SALES1 > SELECT * FROM customers ; ID NAME ---------- ------------------------- 1 SALES1 SALES1 > SALES1 > COMMIT ; Commit complete.
כעת ניתן שוב את ההרשאות על הפרוצדורה ליוזר sales2
SALES1 > GRANT EXECUTE ON customers_proc TO sales2 ; Grant succeeded. SALES1 > SALES1 > CONN sales2/sales2 Connected. SALES2 > SALES2 > SET SERVEROUTPUT ON SALES2 > SALES2 > EXEC sales1.customers_proc (1, 2, 'David') BEGIN sales1.customers_proc (1, 2, 'David'); END; * ERROR at line 1: ORA-00942: table or view does not exist ORA-06512: at "SALES1.CUSTOMERS_PROC", line 9 ORA-06512: at line 1 SALES2 > SALES2 > EXEC sales1.customers_proc (2, 2, USER) BEGIN sales1.customers_proc (2, 2, USER); END; * ERROR at line 1: ORA-00942: table or view does not exist ORA-06512: at "SALES1.CUSTOMERS_PROC", line 13 ORA-06512: at line 1 SALES2 > SALES2 > COMMIT ; Commit complete. SALES2 > SALES2 > CREATE TABLE customers 2 (id number, 3 name varchar2(25)) ; Table created. SALES2 > SALES2 > EXEC sales1.customers_proc (1, 2, 'David') 1 row was inserted PL/SQL procedure successfully completed. SALES2 > SALES2 > EXEC sales1.customers_proc (2, 2, USER) 1 rows was updated PL/SQL procedure successfully completed. SALES2 > SALES2 > SALES2 > SELECT * FROM customers ; ID NAME ---------- ------------------------- 2 SALES2 SALES2 > SALES2 > CONN sales1/sales1 Connected. SALES1 > SALES1 > SELECT * FROM customers ; ID NAME ---------- ------------------------- 1 SALES1 SALES1 >
ניתן לראות כי הפעם יוזר sales2 לא יכל לגשת לטבלת sales1 למרות שקיבל הרשאה על הפרוצדורה, עם זאת ברגע שנוצרה תחת הסכמה שלו טבלה עם אותו שם, הפרוצדורה יכלה לשרת אותה.
לסיכום –
ב Definer Right נשתמש כאשר נרצה לתת את ההרשאות לטבלאות שלנו באמצעות תוכנית PLSQL ולא ישירות.
ב Invoker Right נשתמש כאשר נרצה לייצר קוד גנרי אשר יוכל לשמש טבלאות בעלות אותו שם בסכמות שונות.