姜太阁

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

所有者权限

在Oracle中,系统权限、对象权限以及他们的集合角色权限,是一个相对复杂的安全体系。在前一篇《使用Role权限体系》(http://space.itpub.net/17203031/viewspace-691917)中,已经进行初步介绍。存储过程作为Schema对象下的程序单元,在进行Role处理时有一些特殊之处。今天我们继续介绍存储过程的权限体系:所有者权限调用者权限

在存储过程中,我们常常面对这样一个场景:用户A下有一个存储过程(或者函数体、包体)P,中间引用了对象X。在编译存储过程时,是要求用户A有对象X的权限的,如果没有,则系统报编译错误。当成功进行编译之后,用户A将执行execute存储过程P的权限赋给了用户B。但是用户B这时候不一定拥有X的使用权限,此时B能够成功执行存储过程P呢?我们通过一个简单实验,来证实一下。

实验环境准备

先准备用户test,除了具备基本的connect和resource角色权限之外,处于实验目的,赋给select any dictionary的系统权限给test。

SQL> conn sys/sys@otstest as sysdba;

Connected to Oracle Database 10g EnterpriseEdition Release10.2.0.1.0

Connected as SYS

SQL>

SQL> create user test

 2   identified by test;

User created

SQL> grant resource to test;

Grant succeeded 

SQL> grant connect to test;

Grant succeeded

SQL> grant select any dictionary to test;

Grant succeeded

 

Select any dictionary的系统权限意味着用户可以访问数据字典视图层面的视图对象数据,而且不会因为存储过程对角色权限的剥离效应而受到影响。

SQL> conn test/test @otstest;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as test

SQL> select count(*) fromdba_objects;

 COUNT(*)
--------------
 53305

SQL> create or replace procedure p_test_nc
 2 is
 3   i number;
 4 begin
 5   select count(*)
 6   into i
 7   from dba_objects;
 8 
 9   dbms_output.put_line(to_char(i));
 10 end;
 11 /
Procedure created
SQL> set serveroutput on size 1000;
SQL> exec p_test_nc;
53306
PL/SQL procedure successfully completed

可见,授予select any dictionary的用户test可以对dba_objects视图进行访问操作。同时,存储过程p_test_nc也可以顺利的编译执行。

实验一 —— 所有者权限

准备好的实验环境,我们准备进行第一个项目实验。建立一个新用户ts,只有执行test用户下p_test_nc存储过程权限,但是没有访问dba_objects视图权限,看实际效果。

SQL> conn sys/sys@otstest as sysdba;
Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as SYS

SQL> create user ts
 2   identified by ts;

User created
SQL> grant resource to ts;
Grant succeeded

SQL> grant connect to ts;
Grant succeeded

//用户ts只具有基本的连接和创建对象权限。

SQL> conn test/test@otstest;
Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as test

//将p_test_nc执行权限授权给ts
SQL> grant execute on p_test_nc to ts;
Grant succeeded

之后,我们检查ts用户下,p_test_nc的执行情况。

SQL> conn ts/ts@otstest;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as ts
 
SQL> select count(*) from dba_objects;
 
select count(*) from dba_objects

//ts用户没有dba_objects权限,显示访问必然没有结果;
ORA-00942:表或视图不存在

SQL> set serveroutput on size 1000;
SQL> exec test.p_test_nc;

53306

PL/SQL procedure successfully completed

结果显而易见,ts虽然没有访问dba_objects权限,但是因为拥有执行p_test_nc的权限,在执行p_test_nc的时候,也是可以在方法中访问到dba_objects。显然,此时ts在p_test_nc上借用了test用户对于dba_objects用户的权限,也就是对象所有者权限。

进一步证明我们的实验,可以进行些变化。

--当所有者权限失去时,即使调用者拥有权限也是无用的。

 

SQL> conn sys/sys@otstest as sysdba;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as SYS

//回收了test用户上的select any dictionary权限,此时test对dba_objects对象权限消失;
SQL> revoke select any dictionary from test;
Revoke succeeded

//赋予ts用户select any dictionary权限,这样ts就能访问dba_objects了;
SQL> grant select any dictionary to ts;
Grant succeeded

SQL> conn ts/ts@otstest;
Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as ts

SQL> set serveroutput on size 1000;
SQL> select count(*) from dba_objects;//可以访问对象

 COUNT(*)
----------
    53306

SQL> exec test.p_test_nc;

begin test.p_test_nc; end;

ORA-06550:第1行,第12列:
PLS-00905:对象TEST.P_TEST_NC无效
ORA-06550:第1行,第7列:
PL/SQL: Statement ignored

 

我们看到了一些“诡异现象”,ts用户拥有dba_objects对象访问权限,同时也有执行p_test_nc的权限,但是执行的时候却报错,认为对象无效。

唯一的原因就是因为test用户失去了dba_objects对象的权限。而ts在调用p_test_nc时使用的是dba_objects的权限。

上面,我们就介绍了Oracle在存储过程中使用的权限配置“所有者权限”。简单的说,当执行一个程序体(存储过程、函数和包等)的时候,方法体内部使用的权限体系为当前该程序体所有者的权限体系,而与调用方法的用户无关。存储过程p_test_nc此时,无论是谁在执行,权限体系都是该存储过程的所有者test的权限。

所有者权限是Oracle使用的默认权限选择方式,在使用的时候很方便。使用者只要拥有简单的对象执行权限就可以了,无需顾及自己是否有权限访问方法中使用的对象。

调用者权限

 

有了前面对所有者权限的介绍,调用者权限的含义就相对容易理解了。调用者权限体系就是执行方法体的时候,使用的权限按照调用者权限体系来判断。一个方法的执行,调用者除了要拥有方法的执行权限,还要拥有方法中使用对象的权限才可以。

实验二——调用者权限

我们继续实验一的环境。注意,此时test用户没有select any dictionary权限,而ts拥有。

SQL> conn test/test@otstest;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
 
Connected as test

SQL>

SQL> create or replace procedure p_test_nc
 2 is
 3   i number;
 4 begin
 5   select count(*)
 6   into i
 7   from dba_objects;
 8 
 9   dbms_output.put_line(to_char(i));
 10 end;
 11 /

Warning: Procedure created with compilation errors

检查报错信息,还是因为没有dba_objects的权限。

 

SQL> select * from user_errors;

NAME      TYPE       SEQUENCE       LINE   POSITION               TEXT  
------------------------------- ---------- ---------- --------------------------------------
P_TEST_NC PROCEDURE       1         7         8         PL/SQL: ORA-00942:表或视图不存在    
P_TEST_NC PROCEDURE       2         5         3         PL/SQL: SQL Statement ignored 

此时,我们如果在方法定义上加入authid current_user关键字,就可以将存储过程变化为调用者权限。

SQL> create or replace procedure p_test_nc 
 2 authid current_user
 3 is
 4   i number;
 5 begin
 6   select count(*)
 7   into i
 8   from dba_objects;
 9 
 10   dbms_output.put_line(to_char(i));
 11 end;
 12 /

Warning: Procedure created with compilation errors

显然,还在因为dba_objects没有权限而报错,毕竟不管是什么体系,test目前是没有对象权限的。不过,为了实验成功,还是要让test能顺利编译过p_test_nc方法。

SQL> conn sys/acca@otstest as sysdba;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as SYS

SQL> grant select any dictionary to test;
Grant succeeded

切换回ts用户,注意此时他是拥有select any dictionary权限的。

SQL> conn ts/ts@otstest;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as ts

SQL> exec test.p_test_nc;
PL/SQL procedure successfully completed

SQL> set serveroutput on size 1000;
SQL> exec test.p_test_nc;

53306

PL/SQL procedure successfully completed

SQL> select count(*) from dba_objects;

 COUNT(*)
----------------------
    53306

此时,执行顺利成功。因为此时test和ts都拥有select any dictionary权限,所以即使在调用者权限下,也是会成功的。那么,如果我们收回ts上的权限,会如何呢?

SQL> conn sys/acca@otstest as sysdba;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as SYS

SQL>revoke select any dictionary from ts; //权限回收
Revoke succeeded

SQL> conn ts/ts@otstest;
Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as ts

SQL> select count(*) from otstest;
'select count(*) from otstest' ORA-00942:表或视图不存在
SQL
> exec test.p_test_nc;
'begin test.p_test_nc; end;' ORA-00942:表或视图不存在 ORA-06512:在"TEST.P_TEST_NC", line 6 ORA-06512:在line 1

此时,就看出调用者权限的差异了。Test始终有dba_objects的权限,而ts在之后被取消了select any dictionary的权限。如果是所有者权限,ts调用p_test_nc是没有问题的。但是此时报错,说明此处使用的ts调用者权限。

调用者权限与role权限剥离现象

结合之前介绍的role权限剥离的现象,在调用者权限下,这种现象还有吗?我们下面的实验来证实。

继续上面实验的环境,用户ts已经失去了对dba_objects能访问的权限。Test用户拥有select any dictionary系统权限。方法p_test_nc调节为调用者权限。

--调用者权限与role剥离情况

SQL> conn sys/acca@otstest as sysdba;
Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as SYS

SQL> grant select_catalog_role to ts;
Grant succeeded

对对象ts赋予select_catalog_role角色,该角色是能够访问dba_objects的,但是在所有者权限体系下,角色权限会被剔除。

SQL> conn ts/ts@otstest;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as ts

SQL> select count(*) from dba_objects;

 COUNT(*)
--------------------
  53306

SQL> set serveroutput on size 1000;
SQL> exec test.p_test_nc;

53306

PL/SQL procedure successfully completed

注意:我们发现,调用者权限p_test_nc方法应该使用调用者ts的权限。此时ts只有一个select_catalog_role角色权限与dba_objects有关联。可以猜想:在调用者方式下,非所有者调用时不会发生角色权限被剔除的现象。

SQL> conn sys/acca@otstest as sysdba; 

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as SYS

SQL> revoke select any dictionary from test;
Revoke succeeded

SQL> grant select_catalog_role to test;
Grant succeeded

SQL> conn test/test@otstest;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as test

SQL> select count(*) from dba_objects;

 COUNT(*)
--------------------------
  53306

SQL> set serveroutput on size 10000;
SQL> exec p_test_nc;
'begin p_test_nc; end;' ORA-06550:第1行,第7列: PLS-00905:对象TEST.P_TEST_NC无效 ORA-06550:第1行,第7列: PL/SQL: Statement ignored

但是对于p_test_nc方法的所有者test来说,调用权限并没有解决role权限剔除的问题。依然存在存储过程角色剔除问题。

SQL> select * from dba_role_privs where grantee in ('TS','TEST');

GRANTEE                       GRANTED_ROLE          
------------------------------ -----------------------
TEST                          RESOURCE             
TS                            CONNECT                
TEST                          SELECT_CATALOG_ROLE    
TS                            SELECT_CATALOG_ROLE  
TEST                          CONNECT               
TS                            RESOURCE               

6 rows selected

通过上述的实验,我们可以得到如下的经验:

  • 所有者权限和调用者权限是Oracle对存储过程等代码结构提供的独特权限组织模式。二者互为补充,应对不同的需求状况;
  • 即使在调用者模式下,可以一定程度的避免role剔除现象,我们还是不建议使用role权限管理用户;
  • 调用者权限体系在Oracle预定义方法、过程中大量采用,在进行开发的时候,如果遇到类似的问题和Bug,可以从调用者权限的角度去寻求解决方法;
posted on 2013-01-07 11:05  姜太阁  阅读(2372)  评论(0编辑  收藏  举报