查角色间接获得的系统权限必须连查dba_role_privs和role_sys_privs两个视图,仅查dba_sys_privs或user_sys_privs会漏掉绝大多数权限,因oracle默认不展开角色权限。

查角色间接获得的系统权限,必须连查两个视图
只查 DBA_SYS_PRIVS 或 USER_SYS_PRIVS 会漏掉绝大多数权限——因为 Oracle 默认不把角色里的权限“展开”存进系统权限视图。真正要看到用户因角色而拥有的系统权限(比如 CREATE TABLE 来自 RESOURCE 角色),得手动拼两层查询:
- 先查用户被授予了哪些角色:
SELECT granted_role FROM DBA_ROLE_PRIVS WHERE grantee = 'SCOTT' - 再对每个角色查它自带的系统权限:
SELECT privilege FROM ROLE_SYS_PRIVS WHERE role = 'RESOURCE'
注意:ROLE_SYS_PRIVS 不递归——如果 APP_ADMIN 角色里又包含了 SELECT_CATALOG_ROLE,后者的权限不会自动出现在结果里,得再查一层。
用 UNION ALL 合并直接权限 + 角色权限(推荐日常排查)
想一次性看到当前用户所有生效的系统权限(含直授和角色继承),最实用的写法是把两部分用 UNION ALL 拼起来,再去重:
SELECT DISTINCT privilege FROM ( SELECT privilege FROM USER_SYS_PRIVS UNION ALL SELECT rp.privilege FROM ROLE_SYS_PRIVS rp WHERE rp.role IN (SELECT granted_role FROM USER_ROLE_PRIVS) ) ORDER BY privilege;
这个查询不需要 DBA 权限,普通用户可执行;但要注意它反映的是“授权快照”,不是实时会话状态——刚执行 SET ROLE NONE 后,结果不会立刻变。
查别人的角色权限链,DBA_SYS_PRIVS 不顶用
很多人误以为 DBA_SYS_PRIVS WHERE GRANTEE = 'SCOTT' 能查出 SCOTT 的全部系统权限,其实它只返回直接授予的权限。SCOTT 的 CREATE SESSION、CREATE TABLE 等大概率来自 CONNECT 或 RESOURCE 角色,根本不会出现在这里。
- 查别人有哪些角色:
SELECT granted_role FROM DBA_ROLE_PRIVS WHERE grantee = 'SCOTT' - 查某个角色定义(如 RESOURCE):
SELECT privilege FROM DBA_SYS_PRIVS WHERE grantee = 'RESOURCE'—— 注意这里grantee是角色名,不是用户名 -
DBA_SYS_PRIVS和ROLE_SYS_PRIVS字段结构不同:DBA_SYS_PRIVS有ADMIN_OPTION,ROLE_SYS_PRIVS没有
验证当前会话真实可用的权限,只看 SESSION_PRIVS
当你改了角色、执行了 SET ROLE、或者怀疑权限没生效,SESSION_PRIVS 是唯一可信的依据:
SELECT * FROM SESSION_PRIVS;
它只有一列 PRIVILEGE,干净无干扰;执行 SET ROLE ALL 后立刻刷新,而 USER_SYS_PRIVS 保持不变。但它不包含对象权限,也不反映角色是否默认启用——只回答一个问题:“此刻我能干啥”。
递归展开角色链在生产审计中是刚需,但日常查问题时,查到第二层(角色→其直接权限)基本够用;再往下容易陷入无限嵌套,且很多中间角色只是管理封装,实际不带新权限。











