查角色系统权限应使用role_sys_privs视图,因其专门描述角色包含的系统权限;dba_sys_privs仅记录用户或角色直接被授予的权限,不反映角色内部权限结构。
查角色的系统权限该用 role_sys_privs,不是 dba_sys_privs
因为 dba_sys_privs 只存「用户或角色直接被授予」的系统权限,而角色本身不执行操作,它只是权限容器;真正描述「某个角色包含哪些系统权限」的视图是 role_sys_privs。如果你在 dba_sys_privs 里查 grantee = 'connect' 却没结果,不是权限不存在,而是找错了表。
常见错误包括:
- 把角色名写成小写(如
'connect'),但 Oracle 默认存储为大写,必须用'CONNECT' - 误查
DBA_ROLE_PRIVS,它只告诉你「谁被授了这个角色」,不展示角色内部有哪些权限 - 漏掉角色嵌套:如果角色 A 被授给了角色 B,而你只查 A,不会自动看到 B 的权限
ROLE_SYS_PRIVS 查询要加条件才实用
直接 SELECT * FROM ROLE_SYS_PRIVS 会返回上千行,实际排查时应聚焦目标角色:
- 查单个角色:
SELECT PRIVILEGE, ADMIN_OPTION FROM ROLE_SYS_PRIVS WHERE ROLE = 'RESOURCE'; -
ADMIN_OPTION为YES表示该角色可被进一步授予他人(带WITH ADMIN OPTION)——这是权限扩散高风险点 - 想看多个角色:用
IN ('RESOURCE', 'CONNECT'),但注意大小写和引号匹配 - 不要依赖
GRANTABLE字段——它在ROLE_SYS_PRIVS中不存在,那是DBA_TAB_PRIVS里的字段
为什么查不到刚授给角色的权限?先确认三件事
执行 SELECT * FROM ROLE_SYS_PRIVS WHERE ROLE = 'MY_ROLE' 返回空,并不等于没授权成功:
- 当前用户没有
SELECT_CATALOG_ROLE或DBA权限,ROLE_SYS_PRIVS对普通用户不可见——改用SESSION_PRIVS看当前会话生效权限(含角色继承) - 角色名拼错,或建角色时用了双引号(如
"my_role"),此时必须严格按大小写+引号匹配查询 - 权限刚授予但未提交(在 PL/SQL 块中执行
GRANT后忘了COMMIT),事务未持久化
查角色权限不能只看一层,得结合 ROLE_ROLE_PRIVS
角色可以互相授予,比如 APP_ADMIN 包含 SELECT_CATALOG_ROLE,而后者又含 SELECT ANY DICTIONARY。只查 ROLE_SYS_PRIVS 会漏掉这种间接路径:
- 先查角色直接拥有的系统权限:
SELECT PRIVILEGE FROM ROLE_SYS_PRIVS WHERE ROLE = 'APP_ADMIN'; - 再查它包含哪些角色:
SELECT GRANTED_ROLE FROM ROLE_ROLE_PRIVS WHERE ROLE = 'APP_ADMIN'; - 对每个
GRANTED_ROLE递归查ROLE_SYS_PRIVS,才能拼出完整权限集 - 生产环境审计时,必须展开到最底层角色,否则可能低估权限范围
查角色权限最易被忽略的点:角色是否被设为默认(DEFAULT ROLE)。即使用户已被授予某角色,若未设为默认,该角色在会话中不激活,SESSION_PRIVS 也查不到其权限——这导致权限看似存在,实则不可用。











