Oracle用户对象权限体系是Oracle数据库安全管理中重要的组成部分。Oracle用户权限是一套灵活可配置的管理体系。本篇我们从几个使用Oracle权限体系中的问题细节入手,做一些有趣的尝试。
1、 角色role循环赋予实验
角色权限、系统权限和对象权限,三者构成了Oracle权限体系的主干。其中,系统权限(system privilege)和对象权限(object privilege)是原子性权限,也就是不能相互之间包括容纳。
而角色权限(role privilege)具有两个特性,其一是可自定义特性,其二是可包容嵌套特性。所谓可包容嵌套特性就是说角色可以包括其他的系统权限和对象权限,甚至包括其他角色权限。那么,会不会出现角色之前的循环授予问题呢?我们通过下面的实验来确定。
//自定义两个空权限角色;
SQL> create role r_t;
Role created
SQL> create role r_m;
Role created
//相互尝试赋予权限;
SQL> grant r_t to r_m;
Grant succeeded
SQL> grant r_m to r_t;
grant r_m to r_t
ORA-01934: 检测到循环的角色授权
实验结论显而易见。Oracle在进行grant角色相关授权的时候,会自动进行循环检测,如果发现循环,就禁止掉操作。
这让我们想起Oracle对死锁也有类似的检测机制,详见笔者的文章《Oracle中的死锁》(http://space.itpub.net/17203031/viewspace-682115)。
2、 角色权限在存储过程中的剔除效应
角色的确是一种很方便的权限集合组织方式,在很多系统中也是广泛应用。但是在Oracle中,使用角色权限role privilege是要格外小心的,特别是进行数据库开发过程中。因为Oracle存储过程等结构对角色权限有剔除效应。
首先我们准备实验环境。
//建立实验角色r_cat_role
SQL> create role r_cat_role ;
Role created
//授予系统权限select any dictionary给实验角色
SQL> grant select any dictionary to r_cat_role;
Grant succeeded
//创建用户
SQL> create user mytest identified by mytest;
User created
SQL> grant create session to mytest;
Grant succeeded
SQL> grant r_cat_role to mytest;
Grant succeeded
SQL> grant create procedure to mytest;
Grant succeeded
实验中,mytest用户只具有基本的连接权限和以后实验用到的create procedure权限。此外只有使用的角色权限r_cat_role。
角色权限r_cat_role中具有了select any dictionary的系统权限。该权限下,用户可以访问到Oracle的大部分元数据视图。而这个权限对于一般用户而言显然是不具备的。
SQL> conn mytest/mytest@ora11g;
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0
Connected as mytest
SQL> select count(*) from dba_objects;
COUNT(*)
----------
72282
dba_objects视图是元数据字典的一个组成部分。mytest用户在接受角色权限r_cat_role之后,具有了在SQL中直接使用的权限。下面我们构造存储过程如下:
SQL> create or replace procedure P_TEST_NC
2 is
3 n_res number;
4 begin
5 select count(*)
6 into n_res
7 from dba_objects;
8
9 dbms_output.put_line(to_char(n_res));
10 end P_TEST_NC;
11 /
Warning: Procedure created with compilation errors
SQL> select * from user_errors;
NAME TYPE SEQUENCE LINE POSITION TEXT ATTRIBUTE
---------- ------------ ---------- ---------- ---------- ---------------------------------------- ---------
P_TEST_NC PROCEDURE 1 7 8 PL/SQL: ORA-00942: 表或视图不存在 ERROR
P_TEST_NC PROCEDURE 2 5 3 PL/SQL: SQL Statement ignored ERROR
编译报错,看起来不可思议。明明mytest用户具有dba_objects视图的访问权限,而且在SQL语句直接可以使用。为什么在SP中使用就不可以了呢?
我们说,就是因为访问dba_objects的权限是通过角色授予的。存储过程等Oracle代码结构具有一个特性,就是可以将用户的三层权限(role、system和object)中的role权限剥离掉。
mytest是通过角色r_cat_role来获取到的select any dictionary系统权限的。在进入sp定义的时候,角色就被剥离掉。所以没有对dba_objects访问的权限。
解决问题的办法,就是放弃使用角色权限而直接进行系统权限授予。
SQL> conn sys/oracle@ora11g as sysdba;
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0
Connected as SYS
SQL> revoke r_cat_role from mytest;
Revoke succeeded
SQL> grant select any dictionary to mytest;
Grant succeeded
重新实验,创建存储过程。
SQL> conn mytest/mytest@ora11g;
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0
Connected as mytest
SQL> select count(*) from dba_objects;
COUNT(*)
----------
72283
SQL> create or replace procedure P_TEST_NC
2 is
3 n_res number;
4 begin
5 select count(*)
6 into n_res
7 from dba_objects;
8
9 dbms_output.put_line(to_char(n_res));
10 end P_TEST_NC;
11 /
Procedure created
实验成功。
经过上面的两个实验,我们发现Oracle的role权限不像想象的那么高效,而且存在一定的复杂性。那么实际上,我们真正有很多相同职责的Oracle用户吗?很多时候,我们的系统是不会让Oracle与用户直接联系的,都是通过前端应用以一个统一的名称进行访问。角色特别是自定义角色使用的场景很少。
所以,笔者的想法是,除了进行特定的数据库操作,使用预定义Oracle角色权限外,不要尝试自己去定义角色。此外,对权限还是使用直接的对象、系统权限赋予较好。
3、系统权限和对象权限冲突实验
系统权限中包括一部分与对象有关的内容。如select any table、execute any procedure等。这些和对象权限之间存在一些重叠的部分。那么,会不会出现对特定对象的冲突呢?
首先我们检查一般的情况。
SQL> create user mytest identified by mytest;
User created
SQL> grant connect, resource to mytest;
Grant succeeded
SQL> grant select any table to mytest;
Grant succeeded
在scott用户下。
SQL> conn scott/tiger@orcl;
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as scott
SQL> create table m as select * from all_tables;
Table created
具有select any table的用户mytest是可以直接select用户scott的数据表m的。
SQL> conn mytest/mytest@orcl;
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as mytest
SQL> select count(*) from scott.m;
COUNT(*)
----------
104
尝试可否从scott用户上禁止mytest对m的访问。
SQL> conn scott/tiger@orcl;
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as scott
SQL> revoke select on t from mytest;
revoke select on t from mytest
ORA-01927: 无法 REVOKE 您未授权的权限
可见看出,对Oracle的revoke而言,只能revoke授予过的权限。未授予过的权限,或者尝试对系统权限、对象权限语义的拆分,都是不能做到的。
那么,拥有select any table,就可以任意select了吗?未必。我们一起来继续看。
//在sys用户下,创建数据表t;
SQL> show user
User is "SYS"
SQL> create table t as select * from dba_objects;
Table created
SQL> conn mytest/mytest@orcl;
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as mytest
SQL> select count(*) from sys.t;
select count(*) from sys.t
ORA-00942: 表或视图不存在
可以看出,虽然mytest拥有select any table权限,但是对sys用户下的数据表,是不能访问的。这是Oracle内部对于sys用户核心对象的一种保护措施。
如果要让mytest能访问到sys.t对象,需要进行显示的对象权限object privilege赋值。
SQL> show user
User is "SYS"
SQL> grant select on t to mytest;
Grant succeeded
SQL> conn mytest/mytest@orcl;
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as mytest
SQL> select count(*) from sys.t;
COUNT(*)
----------
51369
显然,sys下的对象往往需要进行显示的对象权限赋值。
4、 结论
上面三个实验,简单挖掘了一下权限体系的一些细节问题。很多时候,我们会遇到很多复杂的需求场景,把握权限系统各层次的本质特性,进行合理评估和分析试验,就能实现很多看似不可能做到的任务。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/17203031/viewspace-701556/ ,如需转载,请注明出处,否则将追究法律责任。