在Oracle8i以前,所有已编译存储对象(包括packages,procedures, functions, triggers, andviews)只能以定义者(Definer)身份解析运行;从Oracle8i开始,Oracle引入调用者(invoker)权限,使得对象可以以调用者身份和权限执行。
- 定义者(Definer)指编译存储对象的所有者.
- 调用者(Invoker)指拥有当前会话权限的模式,这可能和当前登录用户相同或不同(alter session set current_schema 可以改变调用者Schema).
1、使用定义者身份运行——AUTHID DEFINER(默认方式,不指定时就是这种方式):
可以通过在命名程序部分中使用AUTHID DEFINER 关键字来实现。任何用户接收到运行以这种方式编译的程序的权限后,将会以程序所有者的身份运行该程序。
create or replacefunction hr.quarterly_sales
AUTHID DEFINER
as
Begin
end;
2、使用调用者的权限来执行程序——AUTHID CURRENT_USER:
create as replacefunction hr.quarterly_sales
AUTHIDCURRENT_USER
as
Begin
end;
【实例】
1.以Eygle用户(definer)创建2个过程
$ sqlplus eygle/eygle
SQL*Plus:Release 9.2.0.4.0 - Production on Sun Dec 11 11:39:27 2005
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connectedto:
Oracle9iEnterprise Edition Release 9.2.0.4.0 - 64bit Production
Withthe Partitioning option
JServerRelease 9.2.0.4.0 - Production
SQL>create or replace procedure definer_proc
2 as
3 begin
4 for x in
5 ( select sys_context('userenv', 'current_user' ) current_user,
6 sys_context( 'userenv', 'session_user' ) session_user,
7 sys_context( 'userenv', 'current_schema' ) current_schema
8 fromdual )
9 loop
10 dbms_output.put_line( 'Current User: ' || x.current_user );
11 dbms_output.put_line( 'Session User: ' || x.session_user );
12 dbms_output.put_line( 'Current Schema: ' || x.current_schema );
13 end loop;
14 end;
15 /
Procedurecreated.
SQL>
SQL>grant execute on definer_proc to test;
Grantsucceeded.
SQL>
SQL>create or replace procedure invoker_proc
2 AUTHID CURRENT_USER
3 as
4 begin
5 for x in
6 ( select sys_context('userenv', 'current_user' ) current_user,
7 sys_context( 'userenv', 'session_user' ) session_user,
8 sys_context( 'userenv', 'current_schema' ) current_schema
9 fromdual )
10 loop
11 dbms_output.put_line( 'Current User: ' || x.current_user );
12 dbms_output.put_line( 'Session User: ' || x.session_user );
13 dbms_output.put_line( 'Current Schema: ' || x.current_schema );
14 end loop;
15 end;
16 /
Procedurecreated.
SQL>
SQL>grant execute on invoker_proc to test;
Grantsucceeded.
注意invoker权限的本质是引入了AUTHIDCURRENT_USER子句,通过此句Oracle得以使用invoker身份编译执行对象。
2.以test用户(invoker)身份执行
SQL>connect test/test
Connected.
SQL>
SQL>set serveroutput on
SQL>exec eygle.definer_proc
Current User: EYGLE
Session User: TEST
Current Schema: EYGLE
PL/SQLprocedure successfully completed.
SQL>exec eygle.invoker_proc
Current User: TEST
Session User: TEST
Current Schema: TEST
PL/SQLprocedure successfully completed.
注意只有使用invoker者权限执行时,Schema才转换为TEST.
SQL>alter session set current_schema = system;
Sessionaltered.
SQL>exec eygle.definer_proc
Current User: EYGLE
Session User: TEST
CurrentSchema: EYGLE
PL/SQLprocedure successfully completed.
SQL>exec eygle.invoker_proc
Current User: TEST
Session User: TEST
Current Schema: SYSTEM
PL/SQLprocedure successfully completed.
SQL>
通过alter session setcurrent_schema方式修改当前模式之后,我们看到仍然是仅当使用invoker权限执行时,Schmea方切换为SYSTEM.
源文档 <http://www.eygle.com/archives/2005/12/definer_and_invoker_rights.html>