姜太阁

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

角色是我们使用Oracle进行权限管理时候的一个重要方法。通过设置不同类型的角色,组织不同角色可以使用的系统权限和对象权限。之后简单的将不同角色附加给不同用户,这样在管理和维护上都有着很多优势。

但是,实际我们进行开发应用系统时,要慎用role进行权限管理。因为在Oracle中,在一些场景下使用role角色是受到限制的。其中一个不可忽视的问题就是存储过程SP对角色权限的无效现象。

基础说明

先让我们一起看看Oracle权限体系的结构。在Oracle中,用户的权限分为两个层次:对象权限(object privileges)和系统权限(system privileges)。 

对象权限简单说,就是设置的用户可以对哪个对象(数据表、视图、存储过程等)进行何种类型的操作(select、execute等)。这种层次的权限集中在对象层面上,使用grant和revoke进行权限的授权和收回。格式为:grant/revoke <operation> on <objectname> to/from <user>。 

系统权限则是从另一个角度对操作进行的划分。主要是规定该用户在系统中能做什么?比如,创建数据表、查询数据字典、修改存储过程等等。格式通常为:grant/revoke <priv name> to/from <user>。

对象权限和系统权限是用户权限在不同角度划分。以横纵的方式进行权限管理可以让设置更加游刃有余。不过,有一定要注意,无论是对象权限还是系统权限,都是规定用户可以做什么,而不是规定了用户不可以做什么。此外,用户任何操作,在没有显示指定权限说可以这样做的情况下,默认是认为不可以的。这点很重要,充分避免了设置出现矛盾的情况。

对象权限和系统权限是系统预定义的,除了对象名称外,通常不会有自定义的情况。 

而角色权限(role privileges)相当于对对象权限和系统权限的一种归纳。根据不同数据库使用场景和工作角色,Oracle预定义了很多的角色,用户可以根据实际情况进行自定义的角色空间也有很多。

初步介绍完基础,我们进行试验,看看使用角色给我们带来的一些困扰。

实验环境准备

我们使用Oracle 10gR2版本。

SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database10gEnterpriseEdition Release10.2.0.1.0 - Prod
PL/SQL Release10.2.0.1.0 - Production
CORE       10.2.0.1.0  Production
TNS for 32-bit Windows: Version10.2.0.1.0 - Production
NLSRTL Version10.2.0.1.0 - Production

准备一个全新的用户Test,初始只赋予resource和connect权限。

Connected as SYS

SQL> create user test
 2   identified by test;

User created

SQL> grantresourceto test;
Grant succeeded

SQL> grantconnectto test;
Grant succeeded

Connect角色是允许用户登录到Oracle数据库服务器上,其中包括了create session类的系统权限。Resource是默认schema使用的角色之一,允许用户进行简单对象创建,Schema内部对象访问等操作。准备了一个相对干净的环境。

默认用户行为

我们以dba_objects数据字典作为研究对象。

SQL> conn test/test@orcl;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as test

SQL> select count(*) from dba_objects;

select count(*) from dba_objects
 
ORA-00942:表或视图不存在

此处,Oracle对没有权限访问的对象,并不是告诉你说该对象没有权限访问,而是报告说对象不存在。很简单的提示变化,却体现着Oracle跟深层次的信息保护屏蔽作用。因为,对象是否存在,也是一种信息。报错提示信息,很可能会存在信息、结构泄露的漏洞。

显然,仅拥有connect和resource权限,是不能够访问dba_objects视图的。

角色权限select_catalog_role

在预定义角色中,有select_catalog_role角色,作用是赋予进行数据字典视图select权限。

首先切换到sys用户,进行用户test权限的赋予。

SQL> conn sys/sysacca@orcl as sysdba;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as SYS

SQL> grant select_catalog_role to test;
Grant succeeded

SQL> select * from dba_role_privs where grantee='TEST';

GRANTEE           GRANTED_ROLE  ADMIN_OPTION DEFAULT_ROLE
------------------------------ ------------------------------ ------------ ------------
TEST                          RESOURCE               NO          YES
TEST                          SELECT_CATALOG_ROLE  NO          YES
TEST                          CONNECT                NO          YES

回到test用户,进行测试。

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

SQL> select count(*) from dba_objects;

 COUNT(*)
--------------
    51355

设置角色之后,用户可以访问到字典视图dba_objects了。那么,下面我们要编写一个存储过程,中间包括对dba_objects对象的访问。

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 p_test_nc;
 11 /

Warning: Procedure created with compilation errors

出现了报错,该代码没有任何特殊之处。结合刚刚test用户已经可以访问dba_objects的现象,错误是不大会出现的。我们具体查看错误类型信息。

SQL> col name for a15;

SQL> select name, type, sequence,line,position,text 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

第七行的对象报错不存在,显然是dba_objects导致的。那么,test已经拥有了select_catalog_role的角色信息,而且在command窗口中可以访问到dba_objects。而在存储过程中却不能成功呢?

Select any dictionary权限

我们先留待问题,换一个角度来实现这个SP的构建。Oracle具有一个select any dictionary的系统权限,表示的是可以对数据字典进行访问查询。我们观察一下将其赋给test用户后的效果。

首先还是使用sys用户进行权限设置。

SQL> conn sys/sysacca@orcl as sysdba;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as SYS

SQL> revoke select_catalog_role from test;
Revoke succeeded

SQL> grant select any dictionary to test;
Grant succeeded

SQL> select * from dba_role_privs where grantee='TEST';

GRANTEE            GRANTED_ROLE   ADMIN_OPTION DEFAULT_ROLE
------------------------------ ------------------------------ ------------ ------------
TEST                          RESOURCE                      NO          YES
TEST                          CONNECT                       NO          YES

通过sys用户,已经取消了select_catalog_role角色在test上的起效,并且赋予了select any dictionary系统权限给test。下面观察实验现象。

SQL> conn test/test@orcl;

Connected to Oracle Database10gEnterpriseEdition Release10.2.0.1.0
Connected as test

SQL> select count(*) from dba_objects;

 COUNT(*)
--------------
    51356

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 p_test_nc;
 11 /

Procedure created

SP被顺利编译,说明权限设置是问题的关键。 

通过这个小例子和实验,我们可以做出下面的结论:

  • 在进行一般的SQL操作或者匿名块的时候,系统权限、对象权限和role所起到的效果一样的,没有差异;
  • 但是,当在一个存储过程类封装代码的时候,用户执行时角色权限是失效的,之后系统和对象权限是起效的;
  • 综合上述,我们在设置权限的时候,尽量避免使用role进行设置;
posted on 2013-01-07 15:13  姜太阁  阅读(659)  评论(0编辑  收藏  举报