调用者权限与定义者权限的pl/sql子程序
上一篇 / 下一篇 2008-06-02 18:53:22/ 个人分类:工作技术
对于pl/sql子程序的调用来说,具有两种方式:定义者权限和调用者权限。所谓定义者权限,表示的是在执行pl/sql子程序的时候,参考的是创建该pl/sql子程序的用户所拥有的权限。同时,pl/sql子程序在执行时,对于牵涉到的表或者其他对象,也都参考创建该pl/sql子程序的用户所拥有的对象。而执行该pl/sql子程序的用户不需要具有访问创建该pl/sql子程序的用户下的表的权限。缺省情况下,pl/sql子程序都以定义者权限来执行。
比如:
SQL> connect / as sysdba
已连接。
SQL> create user u1 identified by u1;
用户已创建
SQL> grant create session to u1;
授权成功。
SQL> connect u1/u1
已连接。
SQL> select last_name from hr.employees where employee_id=101;
select last_name from hr.employees where employee_id=101
*
ERROR 位于第 1 行:
ORA-00942: 表或视图不存在
SQL> connect hr/hr
已连接。
SQL> CREATE OR REPLACE PROCEDURE p_get_lastname
2 (v_employee_id IN employees.employee_id%TYPE,
3 v_last_name OUT employees.last_name%TYPE) IS
4 BEGIN
5 SELECT last_name
6 INTO v_last_name
7 FROM employees
8 WHERE employee_id = v_employee_id;
9 END;
10 /
过程已创建。
SQL> grant execute on p_get_lastname to u1;
授权成功。
SQL> connect u1/u1
已连接。
SQL> var ls_lastname varchar2(50);
SQL> exec hr.p_get_lastname(101,:ls_lastname);
PL/SQL 过程已成功完成。
SQL> print ls_lastname;
LS_LASTNAME
----------------------------------------------
Kochhar
可以很明显看到,定义者权限中,u1没有权限查看hr.employees表里的数据,但是u1具有执行hr.p_get_lastname的权限,从而它可以获取hr.employees表里的记录。
而定义者权限则不同。它在执行pl/sql子程序的时候,参考的是执行者的权限。同时,pl/sql子程序在执行时,对于牵涉到的表或者其他对象,也都参考执行该pl/sql子程序的用户所拥有的对象。
比如:
SQL> connect / as sysdba
已连接。
SQL> create user u2 identified by u2 ;
用户已创建
SQL> grant create session to u2;
授权成功。
SQL> connect hr/hr
已连接。
SQL> CREATE OR REPLACE PROCEDURE p_get_lastname2
2 (v_employee_id IN employees.employee_id%TYPE,
3 v_last_name OUT employees.last_name%TYPE)
4 authid current_user
5 IS
6 BEGIN
7 SELECT last_name
8 INTO v_last_name
9 FROM employees
10 WHERE employee_id = v_employee_id;
11 END;
12 /
过程已创建。
注意,这里添加的authid current_user就表示该存储过程为调用者权限。
SQL> grant execute on p_get_lastname2 to u2;
授权成功。
SQL> connect u2/u2
已连接。
SQL> var ls_lastname varchar2(50);
SQL> exec hr.p_get_lastname2(101,:ls_lastname);
BEGIN hr.p_get_lastname2(101,:ls_lastname); END;
*
ERROR 位于第 1 行:
ORA-00942: 表或视图不存在
ORA-06512: 在"HR.P_GET_LASTNAME2", line 7
ORA-06512: 在line 1
可以看的很清楚,这里的错误为:ORA-00942: 表或视图不存在。实际也就是hr.p_get_lastname2里访问的employees表不存在于当前u2用户下。
SQL> connect / as sysdba
已连接。
SQL> grant create table to u2;
授权成功。
SQL> alter user u2 quota 5M on users;
用户已更改。
SQL> connect u2/u2
已连接。
SQL> create table employees(employee_id number,last_name varchar2(50)) tablespace users;
表已创建。
SQL> insert into employees values(101,'hansijie');
已创建 1 行。
SQL> commit;
提交完成。
SQL> exec hr.p_get_lastname2(101,:ls_lastname);
PL/SQL 过程已成功完成。
SQL> print ls_lastname;
LS_LASTNAME
-------------------------------------------------
hansijie
可以看到,当我在u2下创建了employees表以后,就会访问到u2下的employees表里的记录了。
对于定义者权限的pl/sql子程序来说,通过角色传入的权限是不能作用于存储过程里面的。比如:
SQL> create user red identified by red;
用户已创建
SQL> grant dba to red;
授权成功。
SQL> connect red/red
已连接。
SQL> create or replace procedure p_test
2 is
3 begin
4 dbms_utility.exec_ddl_statement('grant dba to u1');
5 end;
6 /
过程已创建。
SQL> exec p_test;
BEGIN p_test; END;
*
ERROR 位于第 1 行:
ORA-01031: 权限不足
ORA-06512: 在"SYS.DBMS_SYS_SQL", line 826
ORA-06512: 在"SYS.DBMS_SQL", line 32
ORA-06512: 在"SYS.DBMS_UTILITY", line 550
ORA-06512: 在"RED.P_TEST", line 4
ORA-06512: 在line 1
这时可以看到,说的很清楚,权限不足。但是red用户已经具有了dba权限了,为何还会报权限不足呢?这就是因为这是一个定义者权限的pl/sql子程序,在执行grant dba to u1的时候,不能获得dba这个角色所传递过来的权限。你可以把该存储过程改为调用者权限,表示参考调用者所拥有的权限。
SQL> create or replace procedure p_test
2 authid current_user
3 is
4 begin
5 dbms_utility.exec_ddl_statement('grant dba to u1');
6 end;
7 /
过程已创建。
SQL> exec p_test;
PL/SQL 过程已成功完成。
这时就能正确执行了。