oracle的role算是对sys privilege 和object privilege的打包。

今天深入的测试了下,还算有不少的东西。

role不是schema对象

像table等在一个schema里面不能有同名的schema object,但是可以有同名的table和role,如下。

SQL> conn test1/test1

Connected.

SQL> create role testrole;

Role created.

 

SQL> create table testrole as select *from all_objects;

Table created.

 

SQL> grant select on testrole to testrole;

Grant succeeded.

 

role和schema不同,有全局的意思。

--切换一个用户,把权限放进testrole里面。

SQL> conn test2/test2

Connected.

 

SQL> create table a as select *from obj;

Table created.

 

SQL> grant select on a to testrole;

Grant succeeded.

 

 

--但是话说回来,role testrole是test1用户创建的,用test2赋给其他用户的话是不允许。

SQL> grant testrole to test3;

grant testrole to test3

*

ERROR at line 1:

ORA-01919: role 'TESTROLE' does not exist

 

--用owner用户来赋予role testrole就没问题。

SQL> conn test1/test1

Connected.

SQL> grant testrole to test3;

Grant succeeded.

 

role是基于session级的

 

可以打开两个窗口,使用用户test1,test3来进行测试。

session1:

SQL> conn test1/test1

Connected.

SQL> create role testrole;

Role created.

session2:

SQL> conn test3/test3

Connected.

session1:

SQL> grant select on t1 to testrole;

Grant succeeded.

SQL> grant select on testrole to test3;

Grant succeeded.

session2:

SQL> desc test1.t1

ERROR:

ORA-04043: object test1.t1 does not exist

session2 再次登录:

SQL> conn test3/test3

Connected.

SQL> desc test1.t1

 Name                                      Null?    Type

 ----------------------------------------- -------- ----------------------------

 OBJECT_NAME                                        VARCHAR2(128)

 SUBOBJECT_NAME                                     VARCHAR2(30)

 OBJECT_ID                                          NUMBER

 DATA_OBJECT_ID                                     NUMBER

 OBJECT_TYPE                                        VARCHAR2(19)

 CREATED                                            DATE

 LAST_DDL_TIME                                      DATE

 TIMESTAMP                                          VARCHAR2(19)

 STATUS                                             VARCHAR2(7)

 TEMPORARY                                          VARCHAR2(1)

 GENERATED                                          VARCHAR2(1)

 SECONDARY                                          VARCHAR2(1)

还有一点需要说明一下,如果直接赋予object privilege,在当前session就会生效,这也是和role的一个不同之处。

 

当前session激活role

可以使用set role或者dbms_session.set_role来激活。

 

role的限制

   --> 在pl/sql中的限制

在动态sql中,如果调用某些表的时候,通过role,会有table or view not found这类的exception, 这时候需要通过直接赋予object privilege来修正。

 

    -->创建视图时的问题

创建视图时,很可能会有insuffisicant privilege的错误。可以参见http://space.itpub.net/23718752/viewspace-762805/

 

role的加密

如果10个人用同一个db 账号,但是每个人又需要有不同的权限,可以对role加密。

这样每个人在使用的时候都能够相应的通过密码来激活属于自己的role。

 

SQL> create role user1_role identified by test1;

Role created.

 

SQL> create role user2_role identified by test2;

Role created.

 

SQL> create role user3_role identified by test3;

Role created.

 

SQL> create table t1 as select *from obj;

Table created.

 

SQL> create table t2 as select *from tab;

Table created.

 

SQL> create table t3 as select *from syn;

Table created.

 

SQL> grant select on t1 to user1_role;

Grant succeeded.

 

SQL> grant select on t2 to user2_role;

Grant succeeded.

 

SQL> grant select on t3 to user3_role;

Grant succeeded.

 

SQL> grant user1_role,user2_role,user3_role to test3;

Grant succeeded.

 

---初始化test3

SQL> conn / as sysdba

Connected.

--一下这句很关键,只指定用户test3有connect的角色

SQL> alter user test3 default role connect;

User altered.

 

--使用test3来连入,

SQL> conn test3/test3

Connected.

SQL> select *from session_roles;

ROLE

------------------------------

CONNECT

 

--先查看是否可以访问test1.t1

SQL> desc test1.t1

ERROR:

ORA-04043: object test1.t1 does not exist

 

--尝试无密码直接激活role user1_role

SQL> set role user1_role ;

set role user1_role

*

ERROR at line 1:

ORA-01979: missing or invalid password for role 'USER1_ROLE'

 

--使用密码激活role user1_role

SQL> set role user1_role identified by test1;

Role set.

 

SQL> select *from session_roles;

ROLE

------------------------------

USER1_ROLE

 

SQL> desc test1.t1

 Name                                      Null?    Type

 ----------------------------------------- -------- ----------------------------

 OBJECT_NAME                                        VARCHAR2(128)

 SUBOBJECT_NAME                                     VARCHAR2(30)

 OBJECT_ID                                          NUMBER

 DATA_OBJECT_ID                                     NUMBER

 OBJECT_TYPE                                        VARCHAR2(19)

 CREATED                                            DATE

 LAST_DDL_TIME                                      DATE

 TIMESTAMP                                          VARCHAR2(19)

 STATUS                                             VARCHAR2(7)

 TEMPORARY                                          VARCHAR2(1)

 GENERATED                                          VARCHAR2(1)

 SECONDARY                                          VARCHAR2(1)

 

使用另外一个session,使用同样的账号test3

 

SQL> conn test3/test3

Connected.

 

SQL> select *from session_roles;

ROLE

------------------------------

CONNECT

 

SQL> set role user2_role identified by test2;

Role set.

 

SQL> desc test1.t2

 Name                                      Null?    Type

 ----------------------------------------- -------- ----------------------------

 TNAME                                     NOT NULL VARCHAR2(30)

 TABTYPE                                            VARCHAR2(7)

 CLUSTERID                                          NUMBER

 

 

 

secure application role

关于secure applicaton role可以是对role的高级使用,比如你可以限制某些Ip的机器才能激活某些权限。某些特定条件的用户才能激活某些权限,甚至指定在每天的每个时间段才能激活某些权限。这些复杂的需求直接通过external role,dbms_session.set_role, set role等操作就不能实现,需要更细粒度的控制。

下面就举一个例子,来让指定的用户才能激活某些权限。

SQL> select *from all_users;

USERNAME                          USER_ID CREATED

------------------------------ ---------- ---------

DIP                                    20 06-NOV-13

TSMSYS                                 22 06-NOV-13

TEST1                                  26 07-NOV-13

TEST2                                  30 10-NOV-13

DBSNMP                                 25 07-NOV-13

SYS                                     0 06-NOV-13

SYSTEM                                  5 06-NOV-13

OUTLN                                  11 06-NOV-13

8 rows selected.

 

test1下有个表mv_test, 只能通过用户test2才能访问。

(注意:要实现这个需求,如果对于dba账户来说没有任何限制,因为dba账户本来就可以访问test1.mv_test)

步骤如下:

创建role,指定通过内嵌dbms_session.set_role的包来激活

SQL> conn test1/test1

Connected.

SQL> create role r1 identified using test1.setroles;

Role created.

SQL> grant select on test1.mv_test to r1;

Grant succeeded

SQL> grant r1 to test2;

Grant succeeded.

--注意一定要制定authid current_user

SQL> create or replace package setroles authid current_user as 

  2  procedure setrole;

  3  end;

  4  /

Package created.

 

--创建包体

SQL> create or replace package body setroles as 

  2  procedure setrole as

  3  begin

  4  if(sys_context('USERENV','current_user')='TEST2') then

  5  dbms_session.set_role('R1');

  6  end if;

  7  end;

  8  end;

  9  /

--如果可以,可以把运行这个包的权限开放,但是只有合适的用户才能激活。

SQL> grant execute on test1.setroles to public;

 

--用测试用户连入

SQL> conn test2/test2

Connected.

--查看当前持有的role

SQL> select *from session_roles;

ROLE

------------------------------

CONNECT

RESOURCE

 

SQL> desc test1.mv_test

ERROR:

ORA-04043: object test1.mv_test does not exist

 

--运行指定的包以后,来验证

SQL> exec test1.setroles.setrole;

PL/SQL procedure successfully completed.

 

SQL> select *from session_roles;

ROLE

------------------------------

R1

 

SQL> desc test1.mv_test

 Name                                      Null?    Type

 ----------------------------------------- -------- ----------------------------

 OBJECT_ID                                 NOT NULL NUMBER

 OBJECT_NAME                               NOT NULL VARCHAR2(30)

 CREATED                                   NOT NULL DATE

 

选择另外一个用户来比较

--新创建一个用户。

SQL> conn / as sysdba

Connected.

SQL> create user test3 identified by test3;

User created.

 

SQL> grant connect,resource to test3;

Grant succeeded.

 

SQL> conn test3/test3

Connected.

SQL> select *from session_roles;

ROLE

------------------------------

CONNECT

RESOURCE

 

SQL> desc test1.mv_test

ERROR:

ORA-04043: object test1.mv_test does not exist

--运行指定的包,来验证。

SQL> exec test1.setroles.setrole;

PL/SQL procedure successfully completed.

 

SQL> select *from session_roles;

ROLE

------------------------------

CONNECT

RESOURCE

 

SQL> desc test1.mv_test

ERROR:

ORA-04043: object test1.mv_test does not exist

 

 

还有像external role,global之类的role可能使用不是很广泛,先说到这。后面后加以补充。