为什么Oracle的DBA_SYS_PRIVS被授权者多于USER_SYS_PRIVS和ROLE_SYS_PRIVS
问题原因及解答
1. 你的查询方法存在错误
你用来判断grantee类型的查询逻辑本身不符合Oracle系统视图的定义:
USER_SYS_PRIVS视图仅返回当前登录用户被授予的系统权限,无法查询其他用户的权限配置,自然无法匹配到GRANTEE1的记录- 要判断一个grantee是用户还是角色,应该直接查询存储所有用户、角色元数据的系统视图:
-- 查询是否为数据库用户 SELECT username FROM dba_users WHERE username = 'GRANTEE1'; -- 查询是否为数据库角色 SELECT role FROM dba_roles WHERE role = 'GRANTEE1';
2. DBA_SYS_PRIVS中额外grantee的类型
DBA_SYS_PRIVS 会记录所有系统权限的授予关系,其GRANTEE字段覆盖的主体类型远多于普通用户和自定义角色,常见的额外类型如下:
- PUBLIC:Oracle内置的全局用户组,所有数据库用户默认归属该组,授予PUBLIC的权限会自动继承给所有用户,它既不是独立用户也不是普通角色,因此不会出现在你统计的两个视图中
- Oracle预定义内置角色:比如
DBA、CONNECT、RESOURCE、IMP_FULL_DATABASE等系统自带的角色,默认会有大量系统权限配置,如果你统计ROLE_SYS_PRIVS时权限不足,会漏算这部分角色 - 多租户环境的公用主体:12c及以后的CDB多租户环境中,前缀为
C##的公用用户、公用角色的权限会在根容器的DBA_SYS_PRIVS中记录,如果你在PDB租户内统计用户、角色,会漏掉这部分主体 - 视图权限限制导致的统计误差:如果你的登录账号没有
SELECT ANY DICTIONARY或者DBA权限,查询ROLE_SYS_PRIVS、用户相关视图时只能看到你有权限访问的部分,统计结果自然远小于全量的DBA_SYS_PRIVS数据
3. 正确统计方法
如果你需要统计所有权限对应的主体类型,可以用如下关联查询:
SELECT DISTINCT dsp.grantee, CASE WHEN du.username IS NOT NULL THEN '用户' WHEN dr.role IS NOT NULL THEN '角色' WHEN dsp.grantee = 'PUBLIC' THEN '全局用户组' ELSE '其他特殊主体' END AS grantee_type FROM dba_sys_privs dsp LEFT JOIN dba_users du ON dsp.grantee = du.username LEFT JOIN dba_roles dr ON dsp.grantee = dr.role;
内容的提问来源于stack exchange,提问作者bk_32
相关产品推荐
相关产品推荐

