Oracle - 查询哪些权限被授予哪些对象上的哪些角色

Posted

技术标签:

【中文标题】Oracle - 查询哪些权限被授予哪些对象上的哪些角色【英文标题】:Oracle - Query which Privileges are granted which Roles on which Objects 【发布时间】:2013-06-13 11:13:55 【问题描述】:

我需要查询一个 Oracle 数据库并返回哪些权限被授予哪些角色和哪些对象。因为我将根据我正在创建的数据库管理系统中的配置撤销或授予对象角色的权限。

当我遍历要处理的对象时,我需要知道某个角色是否已被授予对该对象的任何特权。这需要在排队执行GRANTREVOKE 之前完成。

ODP.NET 提供程序不支持运行多个 Oracle 语句, 它们必须逐个运行或封装在 BEGIN END 块中(然后算作单个语句)。有些语句甚至必须放在块内的EXECUTE IMMEDIATE 语句中才能工作。

我知道您可以多次将对象的相同权限授予角色而不会破坏任何内容,但是(如果我错了,请纠正我)从角色中撤消该角色不具有的对象的权限会引发一个异常并中断整个块的执行。

在对 Oracle 数据库执行任何操作之前,我首先会查询完成工作所需的所有信息,因为我发现这对于性能而言是最好的,而不是通过查询每个对象来与服务器打乒乓球,角色或特权...

在处理 Oracle 数据库时,我将刚刚查询的本地信息与配置的信息进行比较,并据此执行不同的操作。

我使用 SQLTracker 并发现 Toad 使用此查询查找授予角色对象的权限并删除了角色 where 子句

SELECT dtp.PRIVILEGE,
       dtp.grantable ADMIN,
       dtp.grantee,
       dtp.grantor,
       dbo.owner,
       dbo.object_type,
       dbo.object_name,
       dbo.status,
       '' column_name
  FROM ALL_TAB_PRIVS dtp, DBA_OBJECTS dbo
 WHERE dtp.TABLE_SCHEMA = dbo.owner AND dtp.table_name = dbo.object_name
       AND dbo.object_type IN
              ('TABLE',
               'VIEW',
               'PACKAGE',
               'PROCEDURE',
               'FUNCTION')
UNION ALL
SELECT dcp.PRIVILEGE,
       dcp.grantable ADMIN,
       dcp.grantee,
       dcp.grantor,
       dbo.owner,
       dbo.object_type,
       dbo.object_name,
       dbo.status,
       dcp.column_name
  FROM ALL_COL_PRIVS dcp, DBA_OBJECTS dbo
 WHERE dcp.TABLE_SCHEMA = dbo.owner AND dcp.table_name = dbo.object_name
       AND dbo.object_type IN
              ('TABLE',
               'VIEW',
               'PACKAGE',
               'PROCEDURE',
               'FUNCTION');

我认为此查询将为我提供所需的信息,但如果使用具有大量对象的非常大的 Oracle 数据库,我担心会出现性能问题。

问:查询 Oracle 数据库上哪些对象的哪些角色授予哪些权限的最佳方法是什么?

我发布的查询只是我自己的建议之一,但由于我在这里提出这个问题,我显然对此不确定,并希望对查询进行一些输入。

我在正确的轨道上吗?需要修改吗?我应该废弃它并使用完全不同的方法吗?

【问题讨论】:

【参考方案1】:

好吧,没有实际检索数据就无法检索数据,因此您必须查询表。 如果您的问题是撤销不存在的权限,您可以为其编写一个函数。 像这样的

create or replace procedure revoke_priv (
    object_owner    all_objects.owner%type , 
    object_name     all_objects.object_name%type , 
    privilege       all_tab_privs.privilege%type , 
    role_name       role_tab_privs.role%type)
authid current_user
as
    err number;
    stmt varchar2(4001);
begin
    stmt := 'revoke ' || privilege || ' on ' || object_owner || '.' || object_name ||' from ' || role_name;
    execute immediate stmt;
exception when others then 
    err := SQLCODE;
    if (err = -1927) then
        dbms_output.put_line('the privilege does not exists for the role');
    else
        raise;
    end if;
end;
/

这就是场景

SQL>create role my_role;

Role created.

SQL>grant select on scott.dept to my_role;

Grant succeeded.

SQL>select role , owner , table_name , PRIVILEGE from role_tab_privs where role = 'MY_ROLE';

ROLE                           OWNER                          TABLE_NAME                     PRIVILEGE
------------------------------ ------------------------------ ------------------------------ ----------------------------------------
MY_ROLE                        SCOTT                          DEPT                           SELECT

SQL>revoke select on scott.dept from my_role;

Revoke succeeded.

SQL>revoke select on scott.dept from my_role;
revoke select on scott.dept from my_role
*
ERROR at line 1:
ORA-01927: cannot REVOKE privileges you did not grant

SQL>grant select on scott.dept to my_role;

Grant succeeded.

SQL>exec revoke_priv('SCOTT','DEPT','SELECT','MY_ROLE');

PL/SQL procedure successfully completed.

SQL>select role , owner , table_name , PRIVILEGE from role_tab_privs where role = 'MY_ROLE';

no rows selected

SQL>exec revoke_priv('SCOTT','DEPT','SELECT','MY_ROLE');
the privilege does not exists for the role

PL/SQL procedure successfully completed.

SQL>drop role my_role;

Role dropped.

【讨论】:

所以你说它足以只查询ROLE_TAB_PRIVS 表? 这是获取角色权限的唯一方法。任何其他方式都会以任何方式隐式使用此表。 似乎是一个很好的答案,但我觉得我不能将其归类为正确的答案,它是一种防止在撤销权限时引发异常的解决方案。 回答您的问题“查询 Oracle 数据库上哪些对象的哪些角色授予哪些权限的最佳方法是什么?” - 就像您从字典中编写的自查询一样。 如果您将 where 子句放在查询中,这很容易,但是如果您想一次获取所有信息,然后通过列表从内存中本地查询以防止乒乓流量,该怎么办。假设您正在尝试管理世界另一端的数据库,如果您有 1000 个用户、40 个角色和 X * 1000 个对象,您将不得不进行大量的乒乓查询才能获得所需的所有信息。一个更好的解决方案是一次获取所有信息,然后只在本地查询 imo。但是又怕查询结果的大小,想知道有没有更好的一次?【参考方案2】:

我最终使用了问题中提供的查询,它似乎工作正常。 我需要的所有信息都在那里。

我最终从UNION ALL 中删除了ALL 部分,因为没有重复的结果给我一个更小的结果集。

SELECT dtp.PRIVILEGE,
       dtp.grantable ADMIN,
       dtp.grantee,
       dtp.grantor,
       dbo.owner,
       dbo.object_type,
       dbo.object_name,
       dbo.status,
       '' column_name
  FROM ALL_TAB_PRIVS dtp, DBA_OBJECTS dbo
 WHERE dtp.TABLE_SCHEMA = dbo.owner AND dtp.table_name = dbo.object_name
       AND dbo.object_type IN
              ('TABLE',
               'VIEW',
               'PACKAGE',
               'PROCEDURE',
               'FUNCTION')
UNION
SELECT dcp.PRIVILEGE,
       dcp.grantable ADMIN,
       dcp.grantee,
       dcp.grantor,
       dbo.owner,
       dbo.object_type,
       dbo.object_name,
       dbo.status,
       dcp.column_name
  FROM ALL_COL_PRIVS dcp, DBA_OBJECTS dbo
 WHERE dcp.TABLE_SCHEMA = dbo.owner AND dcp.table_name = dbo.object_name
       AND dbo.object_type IN
              ('TABLE',
               'VIEW',
               'PACKAGE',
               'PROCEDURE',
               'FUNCTION');

根据查询的数据库大小,查询可能非常昂贵,因此建议只查询一次或使用更多 where 子句来缩小结果集。

【讨论】:

以上是关于Oracle - 查询哪些权限被授予哪些对象上的哪些角色的主要内容,如果未能解决你的问题,请参考以下文章

oracle 如果我授权给第1个用户,这个用户再授权给另第2个.我收回第1个的权限,那第2个个的权限还在么?

oracle确定被授予的对象权限

oracle创建用户后需要授哪些权限

Oracle 查询用户做了哪些操作

oracle权限的分配与回收

oracle 赋予权限后,查询却显示表或视图不存在