• Oracle所有者权限与调用者权限(转)


    所有者权限

    在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,可以从调用者权限的角度去寻求解决方法;
  • 相关阅读:
    实验一报告 20135238&20135207
    第十周
    极客Web前端开发资源大荟萃#022
    一个不错的编程小挑战 没事的时候可以试试
    变形金刚的能量方块(含代码)
    Angular控制器之间的数据通信
    使用HTML5本地 Drag和Drop API(native API)
    用requestAnimationFrame优化你的javascript动画
    模板字符串
    ES6的全新特性:模板字符串
  • 原文地址:https://www.cnblogs.com/javatiger/p/2848874.html
Copyright © 2020-2023  润新知